webdock-mcp-server
by heaventree
README.md
# webdock-mcp-server
[](./LICENSE)
[](https://nodejs.org)
An [MCP](https://modelcontextprotocol.io) (Model Context Protocol) server that gives any
MCP-compatible AI client — Claude Code, Claude Desktop, Cursor, or your own agent — full control
over your [Webdock.io](https://webdock.io) VPS infrastructure: provision and manage servers, take
and restore snapshots, manage SSH/shell users, deploy scripts, configure webhooks, and inspect
account/billing and event history, all through natural language.
It's a thin, well-typed wrapper around the official
[`@webdock/sdk`](https://www.npmjs.com/package/@webdock/sdk) client — the same library that powers
[webdock-cli](https://github.com/webdock-io/webdock-cli) — so every tool call here does exactly
what the equivalent SDK/CLI call would do, with no reimplemented API logic.
## Why
Webdock already has a CLI and a REST API. This exists for the case where the *client* is an LLM:
tool names and parameters are described for an agent to read and choose correctly, destructive
actions are annotated so a host application can gate them, list responses are paginated and
size-capped so they don't blow a context window, and every error message tells the agent what to
check next instead of just repeating an HTTP status code.
## Features
- **56 tools**, full parity with `webdock-cli`'s command surface, across 11 resource domains
- **Two output formats** on every tool — `markdown` (human-readable, default) or `json`
(machine-readable, complete payload) — chosen per call via a `response_format` parameter
- **Async-aware**: mutating server actions accept an optional `wait` flag that blocks until the
triggered operation finishes on Webdock's side, or return immediately with a callback ID you can
poll separately via `webdock_get_operation_status`
- **Client-side pagination** (`limit`/`offset`) and response truncation on every list tool, so a
large account (hundreds of servers/snapshots/events) can't overflow a single tool response
- **Tool annotations** (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) on
every tool, so a host application can distinguish "just looking" from "about to delete a server"
- **Actionable errors** — auth, not-found, conflict, and rate-limit responses are translated into
messages that tell the agent what to do next, not just an HTTP code
- Both **stdio** (default, for local MCP clients) and **streamable HTTP** transports
## Requirements
- Node.js ≥ 18
- A [Webdock.io](https://webdock.io) account and an API token (**Account → API Tokens** in the
dashboard)
## Installation
Clone and build from source (this package isn't published to npm yet):
```bash
git clone https://github.com/heaventree/webdock-mcp.git
cd webdock-mcp
npm install
npm run build
```
This produces `dist/index.js`, the server's entry point.
## Configuration
The server takes exactly one piece of configuration: the `WEBDOCK_API_TOKEN` environment variable.
It's validated at startup — if it's missing, the process prints an error and exits immediately
rather than accepting an unauthenticated tool call.
| Variable | Required | Description |
| --- | --- | --- |
| `WEBDOCK_API_TOKEN` | Yes | Your Webdock API token, from the dashboard's **API Tokens** section |
| `TRANSPORT` | No | `stdio` (default) or `http` |
| `PORT` | No | Port for `http` transport (default `3000`); binds to `127.0.0.1` only |
### Claude Code
Add to `.mcp.json` in your project (or `~/.claude.json` for a global config):
```json
{
"mcpServers": {
"webdock": {
"command": "node",
"args": ["/absolute/path/to/webdock-mcp/dist/index.js"],
"env": {
"WEBDOCK_API_TOKEN": "your-token-here"
}
}
}
}
```
Or register it with the CLI:
```bash
claude mcp add webdock -- node /absolute/path/to/webdock-mcp/dist/index.js
# then set WEBDOCK_API_TOKEN in your environment, or edit the resulting config entry to add an "env" block
```
### Claude Desktop
Add the same `mcpServers` block to your Claude Desktop config file:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
- Linux: `~/.config/Claude/claude_desktop_config.json`
Then restart Claude Desktop.
### Any other MCP client (generic stdio)
Point the client at:
```
command: node
args: ["/absolute/path/to/webdock-mcp/dist/index.js"]
env: { "WEBDOCK_API_TOKEN": "your-token-here" }
```
### Remote / streamable HTTP
```bash
TRANSPORT=http PORT=3000 WEBDOCK_API_TOKEN=your-token-here npm start
```
The server listens on `http://127.0.0.1:3000/mcp`. Put a reverse proxy with TLS and auth in front
of it before exposing it beyond localhost — the server itself does not add authentication on top of
the Webdock API token.
## Tool reference
Every tool accepts an optional `response_format` (`'markdown' | 'json'`, default `'markdown'`).
List tools accept `limit`/`offset` for pagination. Tools that trigger an async Webdock operation
accept an optional `wait` boolean (mirrors the CLI's `--wait`) that blocks until the operation
finishes; leave it `false` (the default) to get a callback ID back immediately and poll it later
with `webdock_get_operation_status`.
### Servers
| Tool | Description |
| --- | --- |
| `webdock_list_servers` | List servers, filterable by account status |
| `webdock_get_server` | Full detail for one server |
| `webdock_create_server` | Provision a server from an image or snapshot |
| `webdock_start_server` / `webdock_stop_server` / `webdock_reboot_server` | Power actions |
| `webdock_archive_server` | Stop and archive a server |
| `webdock_delete_server` / `webdock_cancel_delete_server` | Schedule/undo deletion |
| `webdock_update_server` | Update name/description/notes/next action date |
| `webdock_resize_server_dryrun` / `webdock_resize_server` | Preview/apply a hardware profile change |
| `webdock_reinstall_server` | Wipe and reinstall from an image |
| `webdock_get_server_metrics` | CPU/memory/disk/network usage |
### Server configuration
| Tool | Description |
| --- | --- |
| `webdock_update_server_identity` | Set a server's main domain and alias domains |
| `webdock_renew_server_certificates` | Trigger a Let's Encrypt SSL renewal |
| `webdock_update_server_webserver_settings` | Change web root and reconfigure web server / Let's Encrypt |
| `webdock_update_server_ssh_settings` | Toggle password auth / passwordless sudo / SSH port |
### Server scripts (deployed to a specific server)
| Tool | Description |
| --- | --- |
| `webdock_list_server_scripts` | List scripts attached to a server |
| `webdock_attach_server_script` | Deploy an account script onto a server |
| `webdock_get_server_script` | Get one attached script's details |
| `webdock_execute_server_script` | Run an already-attached script |
| `webdock_remove_server_script` | Detach a script from a server |
### Snapshots
| Tool | Description |
| --- | --- |
| `webdock_list_snapshots` / `webdock_get_snapshot` | List/inspect snapshots (account-wide or per-server) |
| `webdock_create_snapshot` | Create an on-demand snapshot |
| `webdock_restore_snapshot` | Restore a server from a snapshot |
| `webdock_delete_snapshot` | Permanently delete a snapshot |
### SSH keys & shell users
| Tool | Description |
| --- | --- |
| `webdock_list_ssh_keys` / `webdock_create_ssh_key` / `webdock_delete_ssh_key` | Manage account SSH keys |
| `webdock_list_shell_users` | List a server's shell (SSH login) users |
| `webdock_create_shell_user` / `webdock_delete_shell_user` | Manage shell users |
| `webdock_reset_shell_user_password` | Reset a shell user's password |
| `webdock_update_shell_user_keys` | Replace a shell user's attached SSH keys |
| `webdock_get_webssh_token` | Generate a browser-based WebSSH token/URL |
### Catalog (reference data)
| Tool | Description |
| --- | --- |
| `webdock_list_locations` | Datacenter locations |
| `webdock_list_images` | Server images (OS/stack combinations) |
| `webdock_list_profiles` | Hardware profiles (CPU/RAM/disk/price) |
| `webdock_create_custom_profile` / `webdock_delete_custom_profile` | Manage custom hardware profiles |
| `webdock_list_platforms` | Hardware platforms and their resource/pricing ranges |
### Account
| Tool | Description |
| --- | --- |
| `webdock_get_account_info` | Profile and billing summary |
| `webdock_list_archived_servers` | Servers previously archived |
| `webdock_list_account_scripts` | List reusable account scripts |
| `webdock_get_account_script` | Get a script's full content |
| `webdock_create_account_script` / `webdock_update_account_script` / `webdock_delete_account_script` | Manage account scripts |
### Events & webhooks
| Tool | Description |
| --- | --- |
| `webdock_list_events` | Paginated account event history |
| `webdock_list_hooks` / `webdock_get_hook` | List/inspect webhooks |
| `webdock_create_hook` / `webdock_delete_hook` | Manage webhooks |
### Operations
| Tool | Description |
| --- | --- |
| `webdock_get_operation_status` | Poll an async action's status by callback ID |
## Security notes
- Treat `WEBDOCK_API_TOKEN` like any other production credential — it grants full account access.
Don't commit it; pass it via environment/secret manager.
- Destructive tools (`webdock_delete_server`, `webdock_reinstall_server`, `webdock_restore_snapshot`,
`webdock_delete_snapshot`, ...) are marked with `destructiveHint: true` in their MCP annotations.
A host application that wants a confirmation step before destructive calls should gate on that
flag; this server executes whatever a validated tool call asks for.
- `webdock_get_webssh_token` returns a credential (a WebSSH URL granting shell access) in its
response — avoid logging or persisting tool outputs from it.
- If running the `http` transport beyond localhost, put TLS and an auth layer in front of it; the
server itself trusts any caller that can reach it.
## Development
```bash
npm run dev # tsx watch, runs src/index.ts directly
npm run build # tsc -> dist/
npm start # run the built server (stdio)
TRANSPORT=http PORT=3000 npm start # run as streamable HTTP instead of stdio
```
Exercise it manually with the [MCP Inspector](https://github.com/modelcontextprotocol/inspector):
```bash
npx @modelcontextprotocol/inspector node dist/index.js
```
### Project structure
```
src/
├── index.ts # entry point, transport selection, tool registration
├── client.ts # Webdock SDK client singleton, error handling, wait-for-operation helper
├── constants.ts # response size / pagination limits
├── schemas.ts # shared Zod schemas (response_format, pagination, wait, server slug)
├── formatting.ts # markdown table / pagination / truncation helpers
├── types.ts # local structural types for @webdock/sdk response shapes (see below)
└── tools/
├── servers.ts # server lifecycle
├── server-config.ts # identity, SSL, web server settings
├── server-scripts.ts # scripts attached to a server
├── snapshots.ts
├── sshkeys.ts
├── shellusers.ts
├── catalog.ts # locations, images, profiles, platforms
├── account.ts # account info, archived servers, account scripts
├── events.ts
├── hooks.ts # webhooks
└── operations.ts # async operation status polling
```
### A note on `@webdock/sdk`'s types
The published `@webdock/sdk` package's `package.json` has two packaging issues that break normal
TypeScript resolution: its `exports` map only publishes the root entry point (so per-domain types
like `Server`/`Snapshot` can't be imported by name), and its `types` field points at
`./dist/index.d` — missing the `.ts` extension. This project works around both: a `paths` mapping
in `tsconfig.json` points directly at the installed package's `.d.ts` file for type resolution, and
`src/types.ts` defines local structural interfaces for the fields each tool reads — TypeScript's
structural typing means the SDK's own inferred response objects satisfy them without any cast. If a
future SDK release fixes its packaging, these workarounds can be removed.
## Contributing
Issues and PRs are welcome. A few starting points if you want to extend coverage:
- Every tool follows the same shape — see any file in `src/tools/` for the pattern (Zod input
schema with `.describe()` on every field, `readOnlyHint`/`destructiveHint`/`idempotentHint`
annotations, `callSdk()` + `handleApiError()` for the API call, markdown + JSON response
formatting).
- `@webdock/sdk` exposes a few more domains not yet wrapped here: the server web server extras
(database backup scheduling, search-engine blocking, HTTP basic auth, certbot testing) under
`client.servers.webserver.*`, and raw IP block management under `client.webdock.IpBlocks`. PRs
adding tools for these are welcome.
- Run `npm run build` before opening a PR — it must complete without errors.
## License
[MIT](./LICENSE)
## Acknowledgments
- [Webdock.io](https://webdock.io) for the API and the [`@webdock/sdk`](https://www.npmjs.com/package/@webdock/sdk) client
- [webdock-cli](https://github.com/webdock-io/webdock-cli) as the reference for command coverage
- [Model Context Protocol](https://modelcontextprotocol.io) and its [TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues