Back to Discover

wg-easy-mcp

connector

ni-c

Administer wg-easy (WireGuard Easy) v15: manage VPN clients, configs, QR codes and server status

View on GitHub
0 starsSynced Aug 16, 2026

Install to Claude Code

/plugin marketplace add ni-c/wg-easy-mcp

README

wg-easy-mcp

CI npm version npm downloads node license container docs

A Model Context Protocol (MCP) server for administering wg-easy (WireGuard Easy) instances.

Lets MCP clients like Claude Code, Claude Desktop or Codex manage your WireGuard VPN: list, create, update, enable/disable and delete clients, fetch configuration files and QR codes, and inspect the server status — all through the wg-easy v15 REST API.

📖 Full documentation: wg-easy-mcp.ni-c.de

Architecture: an MCP client speaks stdio to wg-easy-mcp, which calls the wg-easy v15 REST API over HTTPS with Basic Authentication

Requirements

  • Node.js ≥ 22
  • A running wg-easy v15+ instance
  • 2FA (TOTP) must be disabled for the account used by this server — the wg-easy API only supports Basic Authentication and does not work with 2FA enabled

Note: The wg-easy REST API is not yet declared stable and may change between releases. This server targets wg-easy v15.

Configuration

Configuration is provided via environment variables:

VariableRequiredDescription
WG_EASY_URLyesBase URL of the wg-easy web UI, e.g. https://vpn.example.com:51821
WG_EASY_USERNAMEyesUsername of a wg-easy admin account
WG_EASY_PASSWORDyesPassword of that account
WG_EASY_INSECURE_TLSnoSet to true to accept self-signed TLS certificates (scoped to the wg-easy connection)

Use https://. With a plain-http URL the Basic Auth credentials and all WireGuard private keys travel unencrypted; the server prints a warning unless the host is local. For self-signed certificates prefer a proper internal CA over WG_EASY_INSECURE_TLS.

Without credentials the server still starts and lists its tools (so registries and inspectors can introspect it), but every tool call fails with setup instructions instead of reaching the wg-easy API.

Installation

Claude Code

claude mcp add wg-easy -s user \
  -e WG_EASY_URL=https://vpn.example.com:51821 \
  -e WG_EASY_USERNAME=admin \
  -e WG_EASY_PASSWORD=your-password \
  -- npx -y wg-easy-mcp

Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "wg-easy": {
      "command": "npx",
      "args": ["-y", "wg-easy-mcp"],
      "env": {
        "WG_EASY_URL": "https://vpn.example.com:51821",
        "WG_EASY_USERNAME": "admin",
        "WG_EASY_PASSWORD": "your-password"
      }
    }
  }
}

Codex

Add to your ~/.codex/config.toml:

[mcp_servers.wg-easy]
command = "npx"
args = ["-y", "wg-easy-mcp"]
env = { WG_EASY_URL = "https://vpn.example.com:51821", WG_EASY_USERNAME = "admin", WG_EASY_PASSWORD = "your-password" }

From source

git clone https://github.com/ni-c/wg-easy-mcp.git
cd wg-easy-mcp
npm install
npm run build
# then use `node /path/to/wg-easy-mcp/dist/index.js` as the command

Docker

A multi-arch image (linux/amd64, linux/arm64) with an SBOM and build provenance is published to GitHub Container Registry:

docker run -i --rm \
  -e WG_EASY_URL=https://vpn.example.com:51821 \
  -e WG_EASY_USERNAME=admin \
  -e WG_EASY_PASSWORD=your-password \
  ghcr.io/ni-c/wg-easy-mcp:latest

The image talks MCP over stdio, so clients need docker run -i (no port is exposed):

{
  "mcpServers": {
    "wg-easy": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "WG_EASY_URL",
        "-e",
        "WG_EASY_USERNAME",
        "-e",
        "WG_EASY_PASSWORD",
        "ghcr.io/ni-c/wg-easy-mcp:latest"
      ],
      "env": {
        "WG_EASY_URL": "https://vpn.example.com:51821",
        "WG_EASY_USERNAME": "admin",
        "WG_EASY_PASSWORD": "your-password"
      }
    }
  }
}

Tools

ToolDescription
list_clientsList all WireGuard clients with status and traffic statistics
get_clientGet the full details of a single client
create_clientCreate a new client (name, optional expiresAt)
update_clientUpdate a client; only the provided fields are changed
enable_client / disable_clientEnable or disable a client
delete_clientPermanently delete a client — two-step, guarded by a confirmation token
get_client_configGet the client's WireGuard .conf file
get_client_qrcodeGet the client configuration as a QR code (SVG)
generate_one_time_linkGenerate a one-time config download link (requires one-time links to be enabled in wg-easy)
get_server_infoRelease/update status, general settings and interface configuration (secrets redacted)

Safety

  • delete_client is a two-step operation: the first call returns a random confirmation token (valid for 5 minutes, bound to the client ID) and only a second call with that exact token deletes the client. Unlike a plain confirm=true parameter, the token cannot be guessed or pre-supplied by the model or by injected text.
  • get_server_info redacts secret fields (privateKey, preSharedKey, password, session/TOTP secrets) from the admin API responses.
  • Everything the wg-easy API returns carries an explicit untrusted-data marker and a 60 000-character budget. Client names, DNS entries and endpoints are free-form strings, so they are marked as data to report rather than instructions to follow, and a single oversized field cannot flood the model's context.
  • A WG_EASY_URL containing embedded credentials (user:password@host) is rejected at startup — they would otherwise be echoed in the startup log and prefixed onto every request.
  • Upstream error bodies are truncated and HTML error pages (reverse proxies) are dropped before being returned to the MCP client.
  • WG_EASY_INSECURE_TLS only relaxes certificate validation for the wg-easy connection — it does not disable TLS verification process-wide.
  • Tools carry MCP annotations (readOnlyHint, destructiveHint, idempotentHint) so hosts can apply appropriate permission policies.
  • Keep in mind that get_client_config and get_client_qrcode return the client's private key, and a generate_one_time_link URL allows an unauthenticated config download — treat tool output as sensitive.

The full trust model is in SECURITY.md and, in prose, at wg-easy-mcp.ni-c.de/guide/security.

Development

npm install
npm run build     # compile TypeScript to dist/
npm test          # run the vitest test suite
npm run lint      # eslint + prettier check
npm run test:coverage

CI runs the suite on Node 22 and 24 and adds npm audit, CodeQL and a Trivy scan of the container image on both architectures. See CONTRIBUTING.md.

The documentation site lives in docs/ with its own manifest:

cd docs && npm install && npm run dev

Releasing

  1. Bump the version in package.json and add a CHANGELOG.md entry.
  2. Commit, then tag and push: git tag -a vX.Y.Z -m "vX.Y.Z" && git push origin main vX.Y.Z

The release workflow runs the test suite, publishes to npm (via trusted publishing, no token, with provenance), creates a GitHub release from the changelog entry and updates the entry in the official MCP Registry (io.github.ni-c/wg-easy-mcp, via GitHub OIDC). The container image is published to GHCR by the CI workflow on the same tag.

server.json lists both an npm and an OCI package; the registry job syncs the version into both before publishing. If it ever fails, fix main and re-run mcp-registry.yml via workflow_dispatch — re-running the tag job checks out the old tree.

License

MIT

Rendered live from ni-c/wg-easy-mcp's GitHub README — not stored, always reflects the source repo.

2 Install Methods

NameDescriptionCategorySource
npm packageInstall via npm (stdio transport)mcp-serverwg-easy-mcp
oci packageInstall via oci (stdio transport)mcp-serverghcr.io/ni-c/wg-easy-mcp:0.3.0

0 Comments

Login required
Log in to post a comment or update on this repo.

No comments yet — be the first to share an update.