关于 wg-easy
wg-easy 是面向管理员的 MCP 服务,用于管理 wg-easy v15 WireGuard VPN 实例。它涵盖客户端生命周期、配置交付和服务器状态,并支持多数写入操作审批及工具筛选。
主要功能
- 01管理客户端的创建、更新、启用和删除
- 02获取客户端配置和二维码
- 03生成一次性配置下载链接
- 04查看服务器状态和客户端流量
- 05多数写入操作需审批
- 06通过预设筛选工具
适用场景
- 01开通或撤销 WireGuard VPN 访问权限
- 02通过文件或二维码分享客户端配置
- 03检查客户端活动和服务器状态
MCP 相关
通过 REST API 向 MCP 客户端提供 wg-easy v15 管理工具。多数写入操作通过 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
一个用于管理 wg-easy(WireGuard Easy)实例的 Model Context Protocol(MCP)服务。
它允许 Claude Code、Claude Desktop 或 Codex 等 MCP 客户端管理你的 WireGuard VPN:列出、创建、更新、启用/禁用和删除客户端,获取配置文件和二维码,以及查看服务状态——所有操作均通过 wg-easy v15 REST API 完成。
11 个工具并非越多越好:设置 WG_EASY_ALLOW_TOOLS=essential
即可改为注册经过精选的 6 个工具。模型从 6 个工具中挑选合适项,远比从 11 个中可靠——请参阅
选择要加载的工具。

有何不同
通过 wg-easy v15 REST API 管理客户端的完整生命周期,包括 .conf
文件、二维码和一次性下载链接。
部分更新会进行合并。 更新时会读取当前客户端状态,只修改你指定的字段, 而不会用默认值覆盖其他内容。
有意不对 disable_client 设置门控。 其他所有写入操作都需要先通过 MCP elicitation 征求用户确认;而此操作只会撤销访问权限,增加操作难度只会让安全的选择变得更慢。
要求
- 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 | 否 | 设置为 true 以接受自签名 TLS 证书(仅对 wg-easy 连接生效) |
WG_EASY_ALLOW_TOOLS | 否 | 以逗号分隔的工具名称、list_* 前缀,或用于精选预设的 essential |
WG_EASY_DENY_TOOLS | 否 | 语法相同;从 WG_EASY_ALLOW_TOOLS 保留的工具中移除相应工具 |
ELICITATION | 否 | false 会用两次调用令牌替代审批对话框。无前缀 |
请使用
https://。 使用纯httpURL 时,Basic Auth 凭据和所有 WireGuard 私钥都会以未加密方式传输;除非主机位于本地,否则服务端会输出警告。对于自签名证书, 建议使用合适的内部 CA,而不是WG_EASY_INSECURE_TLS。
没有凭据时,服务端仍会启动并列出其工具(因此注册表和检查器可以检查它),但每次工具调用都会失败,并显示设置说明,而不会访问 wg-easy API。
选择要加载的工具
WG_EASY_ALLOW_TOOLS 和 WG_EASY_DENY_TOOLS 接受以逗号分隔的工具名称;
末尾的 * 可匹配整个工具系列。essential 是包含以下六个工具的精选预设: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 也不包含:这四个工具要么会不可逆地销毁某些内容,要么会泄露对等方的私钥。需要时请明确指定它们。
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 端点会用六个元工具替代所有服务的工具。
安装
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
支持多架构(linux/amd64、linux/arm64)的镜像已发布到 GitHub Container Registry,并附带 SBOM 和构建来源证明:
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 网页版、
Cursor、LibreChat——可通过 mcp-hub 连接 wg-easy-mcp:一个
容器即可通过 Streamable HTTP 提供多个 stdio MCP 服务,并通过单个密码进行 OAuth 2.1 登录,
还为无法使用 OAuth 的客户端提供长期有效的令牌。它的
/hub 端点通过六个元工具接入所有服务,因此一个连接器即可访问它们,无需在模型上下文中
加入 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 是 hub 自己按服务设置的过滤器,与 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 | 将客户端配置获取为二维码(SVG) |
generate_one_time_link 👤 | 生成一次性配置下载链接,有效期为 5 分钟 |
get_server_info | 版本发布/更新状态、常规设置和接口配置(已隐藏机密信息) |
👤 通过 MCP elicitation 向用户发起请求 · 如果客户端无法显示对话框,则改用两次调用的
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,而不是从实例返回的内容。
有三个答案调整了结构,原因也都相同:对于根节点不是对象的架构,改写后的 2025 年客户端会将其作为 {result: …} 提供服务,因此工具会因请求方不同而返回不同答案。
| 工具 | 原来 | 现在 |
|---|---|---|
list_clients | 裸数组 | {count, clients} |
get_client_config | .conf 文本 | {configuration} |
get_client_qrcode | SVG 标记 | {svg} |
现在,过大的答案会以对象的形式缩短,而不是像字符串那样截断:首先缩短最长的文本字段,然后删除列表条目,并通过 truncated 字段说明截去了什么以及截去了多少内容。按字节偏移截取的文档不是较短的答案,而是无法解析的答案——而且两个通道必须承载相同的值。
对于 wg-easy 发送的内容,描述中将每个字段都设为可选,并允许未知字段;只有此服务构建的内容才是精确的。SDK 会在每个结果发出前根据其架构进行验证,因此,如果结构过于严格,wg-easy 发布版一旦新增字段,就会导致工具彻底失败。
安全
- 有五个工具会询问用户,而不只是询问模型。
create_client、update_client、enable_client、delete_client和generate_one_time_link会通过 MCP 引导在客户端支持时弹出真实对话框。五个工具中只有一个会销毁内容——其他工具会签发 VPN 凭据、重新启用凭据、扩大路由范围,以及生成一个无需身份验证、可发放私钥的 URL。disable_client是唯一从不询问的写入工具:它只能撤销访问权限。如果客户端无法显示对话框,则会改用有效期为 5 分钟、且绑定到精确目标的随机令牌(对于update_client,绑定到精确的编辑操作);这只能证明调用使用相同参数执行了两次,仅此而已。ELICITATION=false会主动采用这种回退方式,但不会移除防护措施。请参阅询问用户。 - 除非是关键信息,否则密钥材料一律脱敏。 字段名按其后缀匹配——
password、passwd、passphrase、secret、token、apiKey、privateKey、preSharedKey,以及所有以totp开头的字段——因此,保存 metrics 令牌 argon2 哈希值的metricsPassword也会受到保护,wg-easy 生成的所有其他<prefix>Secret字段也一样。(key不算后缀:否则publicKey也会被一并处理。)所有嵌套层级中的值都会替换为[redacted]——包括包含 WireGuard _服务端_密钥的get_server_info管理员响应,以及包含各客户端_自身_密钥的list_clients和get_client响应。实时的一次性链接令牌也会在这两个工具的响应中脱敏,因为无需登录即可通过GET /cnf/<token>获取完整配置;expiresAt会保留,因此列表仍会显示链接是否有效。get_client_config、get_client_qrcode和generate_one_time_link是有意设置的例外:这些工具的用途就是向对等端提供配置,而且这是用户主动请求的。 - wg-easy API 返回的所有内容都会带有明确的不可信数据标记,并受 60 000 个字符的预算限制;预算按实际输出的文本计算。客户端名称、DNS 条目和端点都是自由格式字符串,因此会被标记为需要报告的数据,而不是需要遵循的指令;其中的控制字符和双向文本覆盖字符会被剔除(字段名也一样),单个超大字段也无法占满模型的上下文。
- 不会盲目信任实例发送的任何内容。 输出架构声明类型的每个字段都会在边界处进行检查,不符合要求时便会被排除,因此,某条记录中的
id为字符串或数值为1e999,都不会导致整个列表因Output validation error而失败。根本不是客户端记录的条目会计入skipped,而不会被悄悄丢弃。 - 响应正文设有上限(8 MiB;如果声明的
content-length超限,则会在读取任何字节之前拒绝),并且会先读取状态码,再读取正文,因此即使大型代理页面挡在前面,401仍会被识别为401。登录遭拒后,会在十秒内从内存中重复返回该结果,而不是重试。 - 如果
WG_EASY_URL包含嵌入式凭据(user:password@host),则会在启动时拒绝该 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,本服务不支持。
不提供服务端管理功能。 这些工具涵盖客户端生命周期;实例自身的配置、管理员账户和主机均不在工具列表之内。
安全性
- 有五个工具会通过 MCP 征询机制先征求用户同意:
create_client、update_client、enable_client、delete_client和generate_one_time_link。其中只有一个会销毁内容;其他工具之所以也在列表中,是因为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(无需令牌,并附带来源证明),根据变更日志条目创建 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
发布工作流会通过可信发布(OIDC,并附带来源证明)发布到 npm,将多架构容器镜像推送到 GHCR,根据 CHANGELOG 条目创建 GitHub 发布,并更新官方 MCP 注册表中的条目。
贡献
欢迎提交问题、参与讨论和发起拉取请求——请参阅 CONTRIBUTING.md。如需报告漏洞,请使用 私密报告渠道, 而不要公开提交问题;相关政策见 SECURITY.md。
许可证
MIT © Willi Thiel
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。