wg-easy について
wg-easy は、wg-easy v15 の WireGuard VPN インスタンスを管理する管理者向け MCP サーバーです。クライアントのライフサイクル、設定の配布、サーバー状態を扱い、多くの書き込み操作で承認を求め、ツールを絞り込めます。
主な機能
- 01クライアントの作成、更新、有効化、削除
- 02クライアント設定と QR コードの取得
- 03一度限りの設定ダウンロードリンク生成
- 04サーバー状態とクライアント通信量の確認
- 05多くの書き込み操作で承認を要求
- 06プリセットによるツールの絞り込み
活用シーン
- 01WireGuard VPN のアクセス権の付与や取り消し
- 02ファイルや QR コードでのクライアント設定共有
- 03クライアントの利用状況とサーバー状態の確認
MCP 対応
REST API を介して、wg-easy v15 の管理ツールを MCP クライアントに公開します。多くの書き込み操作では MCP elicitation による人の承認を求めますが、クライアントの無効化は対象外です。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y wg-easy-mcpWG_EASY_URLBase URL of the wg-easy web UI, e.g. https://vpn.example.com:51821WG_EASY_USERNAMEUsername of a wg-easy admin account (2FA must be disabled)WG_EASY_PASSWORDシークレットPassword of the wg-easy admin accountWG_EASY_INSECURE_TLSSet to true to accept self-signed TLS certificates (scoped to the wg-easy connection)WG_EASY_READ_ONLYSet to true to register only the read tools (default: false)WG_EASY_ALLOW_TOOLSComma-separated tool names or list_* prefixes to register; 'essential' selects a curated preset (default: all tools)WG_EASY_DENY_TOOLSComma-separated tool names or list_* prefixes to remove from whatever WG_EASY_ALLOW_TOOLS leftローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
11掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| sort | enum | いいえ | 名前の昇順または降順で並べ替えますasc | desc |
| filter | string | いいえ | 任意の名前フィルター(部分文字列一致) |
詳細
wg-easy-mcp
Model Context Protocol(MCP)サーバーです。wg-easy(WireGuard Easy)インスタンスを管理できます。
Claude Code、Claude Desktop、Codex などの MCP クライアントから、WireGuard VPN を管理できます。クライアントの一覧表示、作成、更新、有効化/無効化、削除、設定ファイルや QR コードの取得、サーバーのステータス確認をすべて wg-easy v15 REST API 経由で行えます。
ツール数は11個が上限であって、最低数ではありません。WG_EASY_ALLOW_TOOLS=essential
を設定すると、厳選された6個のツールだけが登録されます。モデルは11個より6個の中からのほうが、はるかに確実に適切なツールを選べます。詳しくは
読み込むツールの選び方をご覧ください。

特長
wg-easy v15 REST API を通じたクライアントのライフサイクル全体に対応し、.conf
ファイル、QR コード、一度限りのダウンロードリンクも扱えます。
部分更新はマージされます。 更新時には現在のクライアント状態を読み取り、指定したフィールドだけを変更します。残りのフィールドがデフォルト値で上書きされることはありません。
disable_client は意図的に承認なしで実行できます。 それ以外の書き込み操作では、MCP のエリシテーションを通じて事前に人の承認を求めます。この操作はアクセスを取り消すだけであり、実行のハードルを上げると、安全な操作ほど遅くなってしまうためです。
要件
- Node.js ≥ 22
- 稼働中の wg-easy v15+ インスタンス
- このサーバーが使用するアカウントでは 2FA(TOTP)を無効にする必要があります。wg-easy API は Basic Authentication のみをサポートしており、2FA が有効な場合は動作しません。
注: wg-easy REST API はまだ安定版として宣言されていません。リリース間で変更される可能性があります。このサーバーは wg-easy v15 を対象としています。
設定
設定は環境変数で指定します。
| 変数 | 必須 | 説明 |
|---|---|---|
WG_EASY_URL | はい | wg-easy の Web UI のベース URL。例:https://vpn.example.com:51821 |
WG_EASY_USERNAME | はい | wg-easy 管理者アカウントのユーザー名 |
WG_EASY_PASSWORD | はい | そのアカウントのパスワード |
WG_EASY_INSECURE_TLS | いいえ | 自己署名 TLS 証明書を受け入れるには true に設定します(wg-easy への接続のみに適用されます) |
WG_EASY_ALLOW_TOOLS | いいえ | カンマ区切りのツール名、list_* プレフィックス、または厳選されたプリセット essential |
WG_EASY_DENY_TOOLS | いいえ | 同じ構文です。WG_EASY_ALLOW_TOOLS で残ったものから除外されます |
ELICITATION | いいえ | false にすると、承認ダイアログが 2 回の呼び出しによるトークンに置き換わります。プレフィックスは付きません |
https://を使用してください。 通常のhttpURL では、Basic Auth の認証情報とすべての WireGuard 秘密鍵が暗号化されずに送信されます。ホストがローカルでない限り、サーバーは警告を表示します。自己署名証明書を使う場合は、WG_EASY_INSECURE_TLSよりも適切な内部 CA の使用をおすすめします。
認証情報がなくてもサーバーは起動してツールを一覧表示するため、レジストリやインスペクターから内容を確認できます。ただし、すべてのツール呼び出しは wg-easy API に到達せず、セットアップ手順を示すエラーになります。
読み込むツールの選択
WG_EASY_ALLOW_TOOLS と WG_EASY_DENY_TOOLS には、カンマ区切りのツール名を指定します。
末尾の * は、該当する一連のツールすべてに一致します。essential は、次の 6 つのツールを厳選したプリセットです:get_server_info、list_clients、get_client、create_client、enable_client、disable_client。
get_client_config、get_client_qrcode、generate_one_time_link は含まれておらず、
delete_client も含まれていません。この 4 つのツールは、取り消せない操作を実行するか、ピアの秘密鍵を渡すためです。必要な場合は、個別に名前を指定してください。
WG_EASY_ALLOW_TOOLS=essential
WG_EASY_ALLOW_TOOLS=essential,get_client_config
WG_EASY_ALLOW_TOOLS=list_clients,get_client_config
WG_EASY_DENY_TOOLS=delete_client,create_client
どのツールにも一致しない項目があると、名前を示して起動が中断されるため、入力ミスによってツールが気付かれないまま非表示になることはありません。存在しないツールを環境変数の設定までさかのぼって探す必要はありません。フィルタリングされたツールは登録されないため、tools/list にも表示されず、tools/call からも不明なツールとして扱われます。これは、WG_EASY_READ_ONLY の設定下で書き込みツールが使えないのと同様です。
これらのサーバーを複数同時に実行する場合は、mcp-hub も選択肢になります。/hub エンドポイントを使うと、各サーバーのツールが 6 つのメタツールに置き換わります。
インストール
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
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
~/.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" }
ソースから
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
SBOM とビルド来歴を含むマルチアーキテクチャイメージ(linux/amd64、linux/arm64)が、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
このイメージは stdio 経由で MCP 通信を行うため、クライアントでは docker run -i が必要です(ポートは公開されません):
{
"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"
}
}
}
}
mcp-hub 経由
ローカルプロセスを起動できないクライアント(ChatGPT connectors、Claude on the web、
Cursor、LibreChat)は、mcp-hub 経由で wg-easy-mcp に接続します。1 つの
コンテナが複数の stdio MCP サーバーを Streamable HTTP 経由で提供し、単一のパスワードの背後に OAuth 2.1 ログインを設け、
OAuth を利用できないクライアント向けに長期間有効なトークンを発行します。/hub エンドポイントは、すべてのサーバーを 6 つのメタツールの背後に配置するため、1 つのコネクターでモデルのコンテキストに N×ツールスキーマを含めずにすべてのサーバーに接続できます。また、両方のプロトコルリビジョンに対応しています。このサーバーが尋ねる質問は、ここを経由して向こう側の人に届きます。
/config/mcp.json は Claude Code の形式を使用するため、エントリにはすでにお持ちのものをそのまま使えます。
{
"mcpServers": {
"wg-easy": {
"command": "npx",
"args": ["-y", "wg-easy-mcp"],
"env": { "WG_EASY_ALLOW_TOOLS": "essential" },
"denyTools": ["delete_client"]
}
}
}
ここでの allowTools と denyTools はハブ独自のサーバーごとのフィルターであり、env 内の *_ALLOW_TOOLS とは異なります。その違いと、そこから起こり得る間違いについては、クライアントガイドをご覧ください。
ツール
| ツール | 説明 |
|---|---|
list_clients | すべての WireGuard クライアントをステータスとトラフィック統計とともに一覧表示します |
get_client | 単一のクライアントの詳細を取得します |
create_client 👤 | 新しいクライアントを作成します(name、省略可能な expiresAt) |
update_client 👤 | クライアントを更新します。指定したフィールドのみが変更されます |
enable_client 👤 | クライアントが再び接続できるようにします。ピアにすでにインストールされた鍵ペアを再び有効にします |
disable_client | クライアントをブロックします。設定と鍵は保持されます |
delete_client 👤 | クライアントを完全に削除します |
get_client_config | クライアントの WireGuard .conf ファイルを取得します |
get_client_qrcode | クライアント設定を QR コード(SVG)として取得します |
generate_one_time_link 👤 | 5 分間有効な、設定ダウンロード用のワンタイムリンクを生成します |
get_server_info | リリース/更新状況、一般設定、インターフェース設定を取得します(シークレットは伏せられます) |
👤 は MCP elicitation を通じて人に確認します。クライアントがダイアログを表示できない場合は、2 回の呼び出しによる
confirm_token に切り替わります。
構造化出力
すべてのツールは outputSchema を宣言し、テキストブロックと併せて structuredContent を返すため、クライアントは文章を解析せずに結果を利用できます。
{
"untrusted": true,
"source": "wg-easy",
"count": 2,
"clients": [{ "id": 1, "name": "laptop", "enabled": true }],
}
untrusted マーカーはテキスト内の文だけでなく、フィールドとして含まれています。構造化データ部分を読み取り、テキストを無視するクライアントには、枠組みのない自由形式のクライアント名、DNS エントリ、エンドポイントがそのまま渡ってしまうためです。delete_client を除くすべてのツールにこのマーカーが含まれています。delete_client が報告するのは、このサーバーから渡された ID だけで、インスタンスから返された情報は含まれないためです。
3 つの回答の形式が変更されました。いずれも同じ理由によるものです。ルートがオブジェクトではないスキーマは、2025 年のクライアントでは {result: …} に書き換えられるため、誰が尋ねるかによってツールの回答が変わってしまいます。
| ツール | 変更前 | 変更後 |
|---|---|---|
list_clients | 配列のみ | {count, clients} |
get_client_config | .conf テキスト | {configuration} |
get_client_qrcode | SVG マークアップ | {svg} |
大きすぎる回答は、文字列として切り詰めるのではなく、オブジェクトとして短縮されるようになりました。最初に最も長いテキストフィールドを短縮し、次にリスト項目を削除します。また、truncated フィールドで、何がどれだけ削られたかを示します。バイトオフセットで切り取られたドキュメントは、小さくなった回答ではなく、解析できない回答です。そして、2 つのチャネルは同じ値を運ぶ必要があります。
wg-easy が送信する内容は、すべてのフィールドを任意とし、未知のフィールドを許可する形で記述されています。厳密なのは、このサーバーが構築する内容だけです。SDK は結果が送信される前にスキーマに照らして検証するため、形を厳格にしすぎると、フィールドを追加した wg-easy のリリースによってツールが完全に失敗するようになります。
安全性
- 5 つのツールは、モデルだけでなく人にも確認を求めます。
create_client、update_client、enable_client、delete_client、generate_one_time_linkは、クライアントが対応していれば、MCP のエリシテーションを通じて実際のダイアログを表示します。この 5 つのうち、何かを破棄するのは 1 つだけです。残りは VPN 認証情報を発行したり、再度有効化したり、ルートを広げたり、認証なしでアクセスでき、秘密鍵を渡す URL を生成したりします。書き込みツールのうち、確認を求めないのはdisable_clientだけです。このツールでできるのはアクセスの取り消しだけです。 クライアントがダイアログを表示できない場合は、5 分間有効で対象(update_clientの場合は対象の編集内容)に厳密に紐付けられたランダムトークンにフォールバックします。これにより証明されるのは、同じ引数で呼び出しが 2 回行われたことだけで、それ以上のことは証明されません。ELICITATION=falseを設定すると、このフォールバックが意図的に使われますが、ガードがなくなることはありません。人に確認を求めるを参照してください。 - 鍵の情報は、目的上必要な場合を除いて、すべての場所で伏せられます。 フィールド名は末尾の文字列で照合されます。対象は
password、passwd、passphrase、secret、token、apiKey、privateKey、preSharedKeyと、totpで始まるすべての名前です。そのため、メトリクストークンの argon2 ハッシュを保持するmetricsPasswordも、wg-easy が生成するその他の<prefix>Secretと同様に保護されます。(keyは末尾の文字列ではありません。対象にするとpublicKeyまで巻き込んでしまうためです。)値はネストの深さにかかわらず[redacted]に置き換えられます。WireGuard の サーバー キーを含むget_server_infoの管理者向けレスポンスも、各クライアント_自身の_キーを含むlist_clientsとget_clientも対象です。ワンタイムリンクの有効なトークンも同じ 2 つのレスポンスから伏せられます。GET /cnf/<token>はログインなしで設定全体を返すためです。expiresAtはそのまま残るため、一覧からリンクが有効かどうかは確認できます。意図的な例外はget_client_config、get_client_qrcode、generate_one_time_linkです。ピアに設定を渡すことがこれらの目的であり、ユーザーから依頼された場合に使います。 - wg-easy API が返すデータには、すべて明示的な信頼できないデータのマーカーが付き、60 000 文字の上限が適用されます。上限は実際に出力されるテキストを基準に計測されます。クライアント名、DNS エントリ、エンドポイントは自由形式の文字列であるため、従うべき指示ではなく報告対象のデータとしてマークされます。また、フィールド名も含めて制御文字と BiDi 上書き文字が取り除かれ、1 つの巨大なフィールドがモデルのコンテキストを埋め尽くすことはありません。
- インスタンスから送られたものは、何も無条件には信用しません。 出力スキーマで型が指定されたフィールドはすべて境界で検証され、条件を満たさない場合は除外されるため、
idが文字列のレコードや1e999を含むレコードが 1 件あっても、一覧全体がOutput validation errorで失敗することはありません。クライアントレコードではないエントリは、黙って破棄せずskippedに計上されます。 - レスポンス本文には上限(8 MiB)があり、
content-lengthで上限超過が宣言されていれば、1 バイトも読み取る前に拒否されます。また、本文より先にステータスが読み取られるため、大きなプロキシページの後ろにある401も401のままです。ログインが拒否された場合は再試行せず、10 秒間メモリから同じ結果を返します。 - 認証情報が埋め込まれた(
user:password@host)WG_EASY_URLは、起動時に拒否されます。そうしなければ、起動ログに出力され、すべてのリクエストに付加されてしまいます。保持されるのはオリジンとパスのみで、起動時の診断メッセージに値が出力されることはありません。 - 上流のエラーレスポンス本文は信頼できないものとしてラベル付けされ、制御文字を除去したうえで 200 文字に切り詰められます。HTML のエラーページ(リバースプロキシ)は、MCP クライアントに返す前に破棄されます。
- 呼び出し元の入力には長さ制限があります。名前とフィルターは 200 文字、アドレスは 64 文字、一覧のパラメーターは 64 件までです。クライアント ID は
Number()の後ではなく、パターンで制限されます。 WG_EASY_INSECURE_TLSが緩和するのは wg-easy 接続の証明書検証だけです。プロセス全体の TLS 検証が無効になることはありません。WG_EASY_READ_ONLY=trueの場合、登録されるのはlist_clients、get_client、get_server_infoだけです。get_client_configとget_client_qrcodeは読み取り操作ですが、この対象には含まれません。読み取る内容はクライアントの秘密鍵そのものであり、鍵の開示を許す読み取り専用モードは、その名前が約束するモードではないためです。- ツールには MCP アノテーション(
readOnlyHint、destructiveHint、idempotentHint)が付いているため、ホストは適切な権限ポリシーを適用できます。 get_client_configとget_client_qrcodeはクライアントの秘密鍵を返し、generate_one_time_linkの URL では認証なしで設定をダウンロードできます。ツールの出力は機密情報として扱ってください。 信頼モデルの全容はSECURITY.mdと、文章形式ではwg-easy-mcp.ni-c.de/guide/securityに記載されています。
意図的に公開していない機能
wg-easy v15以降のみ対応しています。 それより古いバージョンでは、セッションベースの別のAPIが公開されていますが、このサーバーは実装していません。
サーバー管理機能はありません。 ツールが対象とするのはクライアントのライフサイクルです。インスタンス自体の設定、管理者アカウント、ホストはツール一覧の対象外です。
安全性
- 5つのツールでは、MCP elicitationを通じて先に人の承認を求めます。対象は
create_client、update_client、enable_client、delete_client、generate_one_time_linkです。このうち何かを破棄するのは1つだけです。ほかのツールも一覧に含まれているのは、destructiveHintがその動作を分類する軸として適切ではないためです。新しいクライアントはVPNの背後にあるすべてのネットワークにアクセスできる認証情報です。また、update_clientはserverAllowedIpsを拡大でき、enable_clientはピアにすでにインストールされているキーペアを再び有効にできます。 - 承認は正確な変更内容に紐付けられます。そのため、名前の変更を承認しても、その後のルートを拡大する呼び出しまで許可されることはありません。
disable_clientには意図的に承認ゲートを設けていません。アクセスを取り消すことしかないためです。安全な操作に時間がかかるようにするのは、適切なトレードオフではありません。- クライアント名、アドレス、インスタンス独自の文字列は信頼できないデータとして扱い、出力が大きすぎる場合は省略した旨を明記して切り詰めます。
WG_EASY_READ_ONLY=trueを設定すると、読み取りツールのみが登録されます。
ドキュメント
ガイド、ツールリファレンス、安全性に関する注記の全容は、wg-easy-mcp.ni-c.de(ソースはdocs/)にあります。
開発
npm install
npm run build # compile TypeScript to dist/
npm test # run the vitest test suite
npm run lint # oxlint + prettier check
npm run test:coverage
CIではNode 22と24でテストスイートを実行し、両アーキテクチャのコンテナイメージに対してnpm audit、CodeQL、Trivyスキャンも実施します。CONTRIBUTING.mdを参照してください。
ドキュメントサイトは、独自のマニフェストとともにdocs/にあります。
cd docs && npm install && npm run dev
リリース
package.jsonのバージョンを更新し、CHANGELOG.mdにエントリーを追加します。- コミットした後、タグを付けてプッシュします。
git tag -a vX.Y.Z -m "vX.Y.Z" && git push origin main vX.Y.Z
リリースワークフローでは、テストスイートを実行し、npmに公開します(Trusted Publishingを使用し、トークンは不要で、プロヴェナンス付きです)。また、変更履歴のエントリーからGitHubリリースを作成し、公式MCP Registryのエントリー(io.github.ni-c/wg-easy-mcp、GitHub OIDCを使用)を更新します。同じタグで、CIワークフローがコンテナイメージをGHCRに公開します。
server.jsonにはnpmパッケージとOCIパッケージの両方が記載されています。公開前に、レジストリーのジョブが両方のバージョンを同期します。失敗した場合は、mainを修正してから、workflow_dispatchでmcp-registry.ymlを再実行してください。タグのジョブを再実行すると、古いツリーがチェックアウトされます。
リリース
リリースはタグを基準に行います。package.jsonのバージョンを更新し、CHANGELOG.mdの[Unreleased]の注記を新しいバージョンの下に移動してコミットした後、次を実行します。
git tag -s vX.Y.Z -m "vX.Y.Z"
git push origin main vX.Y.Z
リリースワークフローでは、Trusted Publishing(OIDC、プロヴェナンス付き)を通じてnpmに公開し、マルチアーキテクチャ対応のコンテナイメージをGHCRにプッシュします。また、CHANGELOGの該当セクションからGitHubリリースを作成し、公式MCPレジストリーのエントリーを更新します。
コントリビューション
Issue、ディスカッション、プルリクエストを歓迎します。CONTRIBUTING.mdを参照してください。脆弱性については、公開Issueではなく非公開での報告を利用してください。ポリシーはSECURITY.mdに記載されています。
ライセンス
MIT © Willi Thiel
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。