服务器上的 Nginx 只想改配置却不敢动?把 Nginx-UI 跑起来,用 MCP 让 AI 助手帮你安全改配置,再用 cpolar 把面板短时开给自己
先说个我自己踩过很多次的场景:临时要给一台服务器加个反向代理的 location,随手 SSH 上去 vi /etc/nginx/conf.d/xxx.conf,改完脑子一热 nginx -s reload------然后站点 502,自己还不知道哪儿错了。事后回头看,问题通常就两类:语法写错了一个分号,或者 reload 之前根本没跑 nginx -t。
Nginx 配置这事本身不复杂,难的是"安全地改"。跑通的路子是:有个面板能可视化看配置和状态,改完先做语法校验,校验不过就别 reload;更进一步,让 AI 助手通过一套受控的接口来读配置、查状态、执行 reload,人只负责审批。

图 0:整体链路示意------左侧是 Nginx 管理面板,中间是受控接入的 AI 助手节点,右侧是随用随开的临时公网入口。
这篇就落地这条路。用 Nginx-UI 把 Nginx 管起来,用它的内置 MCP 服务把能力交给自己配的 AI 助手,改配置前先 nginx -t 兜底,最后用 cpolar 开一条短时隧道,人在外面也能进面板看一眼。
下面所有命令、返回和断言都是我在本机真跑出来的。有两点先说明:这台机器上没有装 nginx,所以 site 相关的接口会报 500,这是预期结果,我会标注清楚;MCP token 管理、cpolar 固定地址这些我这次没实测的部分,也都如实标了"规划中"。
1 Nginx-UI 是什么,这篇里它负责哪一段

图 1:从启动到 MCP 工具调用的数据流------9000 端口上的服务、面板环节、语法校验环节与 MCP 端点工具清单依次串联。
先把定位说清楚。Nginx-UI 不是 Nginx 的替代品,它是一个用 Go 写的 Nginx 网页管理面板 :读你现有的 Nginx 配置、以图形化方式展示站点与 upstream、提供配置编辑与语法校验、执行 reload/restart,还能管证书、看日志。官方仓库 0xJacky/nginx-ui 目前状态活跃,最新 release 是 v2.6.3,许可证 AGPL-3.0。
它在这篇里只承担一件事:把"Nginx 配置"这件事从 SSH 手改,搬到一个可校验、可回看的界面上。它不动你的 Nginx 本体,而是以"管理端"的身份去读配置文件、调 nginx 命令。
而它真正让它贴合这篇主题的,是一个容易被忽略的能力:内置 MCP 服务 。MCP(Model Context Protocol)是让 AI 助手调用外部工具的协议,Nginx-UI 直接把 nginx_status、reload_nginx、nginx_config_get 这类操作暴露成 MCP 工具。也就是说,AI 助手不用"猜"你的服务器什么样,它可以先查询真实状态,再问你要不要执行。
把两件事合起来看:面板负责看得见 ,MCP 负责接得进来------这正好对上"改配置不敢动"的痛点。
2 环境准备:确认平台,把二进制拉下来
这次实测的环境是 macOS 14.5 (23F79) arm64。Nginx-UI 官方支持列表覆盖得挺宽:macOS 11+、Windows 10+、Linux 2.6.23+(含各类 armv5/armv6/armv7/mips/riscv64/loongarch64)、FreeBSD、OpenBSD、OpenWrt 都在内。你在哪台机器上跑,按对应平台选包就行。
从 releases 页面 下载对应平台包。macOS arm64 是 nginx-ui-macos-arm64-v8a.tar.gz(本次拿到的 v2.6.3 资产为 40840478 字节)。下载后解压、核验,再执行:
bash
mkdir -p /tmp/nginxui-ev && cd /tmp/nginxui-ev
tar -xzf nginx-ui-macos-arm64-v8a.tar.gz
file ./nginx-ui
# Mach-O 64-bit executable arm64
./nginx-ui --version
# nginx-ui 2.6.3 3(566) 826c6fae (go1.27.1 darwin/arm64)
# Yet another Nginx Web UI
看到版本号打印出来,说明二进制能在这台机器上跑。
提醒:正式环境别把二进制丢在
/tmp里跑,找个固定目录(比如/opt/nginx-ui),后面配 systemd 或 launchd 才不会因为临时目录被清掉而失联。
第一件事先确认本地是不是已经装着 nginx。这条不是多余的------后面所有 site 相关功能都依赖它:
bash
which nginx || echo "nginx NOT installed"
# nginx NOT installed
我这边就是没装,所以后面 /api/sites 这类接口会返回 500。你自己的服务器上装了 nginx,那一节就应该正常出数据。
3 启动 Nginx-UI,确认它只听本机
Nginx-UI 的配置来自同目录的 app.ini。默认监听端口是 9000。第一次启动直接用官方 README 里的命令:
bash
cd /tmp/nginxui-ev
./nginx-ui serve --config app.ini
启动日志会打印监听地址:
Server started successfully on [::]:9000
然后开一个新终端验证。这里做两个匿名接口的检查------它们不需要登录,最适合用来判断"服务到底起来没有":
bash
curl -s -w " | HTTP %{http_code}\n" http://127.0.0.1:9000/healthz
# {"status":"ok"} | HTTP 200
curl -s -w " | HTTP %{http_code}\n" http://127.0.0.1:9000/api/install
# {"lock":false,"timeout":true} | HTTP 200
/healthz 返回 {"status":"ok"}、/api/install 返回 200 且 lock 为 false,这两条一起看,说明服务已经就绪、且还没有设置管理员密码 (lock 为 true 就意味着已经初始化过了)。
顺带确认一下端口归属:
bash
lsof -nP -iTCP:9000 -sTCP:LISTEN
# nginx-ui 55876 admin 7u IPv6 ... TCP *:9000 (LISTEN)
看到 nginx-ui 进程占着 9000,就对了。
如果
/healthz打不通,优先按这个顺序查:进程还在不在(ps aux | grep nginx-ui)、端口有没有被别的东西占了(lsof -nP -iTCP:9000)、app.ini里的Port是不是被改过。三个都正常还打不通,再去看启动日志。
另外说一下绑定策略。实测日志显示它监听的是 [::]:9000(双栈全网卡),也就是说局域网内其他设备直接就能访问。这篇的做法是:本地验收阶段够用,一旦要开放到公网,一律走 cpolar 那条隧道,别把 9000 端口在防火墙里裸开。
4 初始化管理员:登录靠 RSA 公钥,不是明文密码
第一次用需要建管理员。这里有个设计值得单独讲:Nginx-UI 的登录不走明文密码。它先用一次性 RSA 公钥把密码加密,再提交。
流程分两步。第一步取公钥:
bash
TS=$(python3 -c "import time;print(int(time.time()))")
FP=$(python3 -c "import uuid;print(uuid.uuid4())")
curl -s -X POST http://127.0.0.1:9000/api/crypto/public_key \
-H 'Content-Type: application/json' \
-d "{\"fingerprint\":\"$FP\",\"timestamp\":$TS}"
# {"public_key":"-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAtB+bXb351P+/xt/...","fingerprint":"..."}
这一步有个坑我实际踩到了:fingerprint 和 timestamp 两个字段都得传 。只传 fingerprint 会直接被打回来------
json
{"scope":"validate","code":406,"message":"Requested with wrong parameters",
"errors":{"timestamp":"required"}}
报错信息其实写得很清楚(timestamp: required),照着补上就行。
第二步,用拿到的公钥加密 {name, password},以 PKCS#1 v1.5 填充,结果做 base64,包成 encrypted_params 提交给 /api/login。登录成功后接口返回 JWT token,同时下发一个 _nginx_ui_secure_session 会话 cookie。
bash
curl -s -X POST http://127.0.0.1:9000/api/login \
-H 'Content-Type: application/json' \
-c cookies.txt \
-d '{"encrypted_params":"<上一步加密后的 base64>"}'
拿到 token 后,用它做一次授权请求确认有效:
bash
TOKEN="<上一步返回的 token>"
curl -s -o /dev/null -w "HTTP %{http_code}\n" \
-H "Authorization: Bearer $TOKEN" http://127.0.0.1:9000/api/nginx/status
# HTTP 200
返回 200 就说明鉴权链路通了。
重要提醒:这个 token 等同于管理员会话,有效期不短。别贴进聊天窗口、别提交进 Git。你这台机器上如果只是自己用,把 token 写在本地变量里用完就丢,是最省心的做法。
5 在面板里读懂状态与配置,reload 前先 nginx -t
现在来看真正的核心:怎么在不慌的前提下改配置。
先看 Nginx 状态。授权后请求状态接口:
bash
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:9000/api/nginx/status
# {"control":null,"level":-1,"message":"","running":false}
这里 running 是 false------因为我这台机器没装 nginx,属预期。你自己的服务器上这里会返回 true,level 也不会是 -1。这条接口建议养成改配置前先打一次的习惯:先知道 Nginx 现在活着,后面万一 reload 出问题,至少能确认"是不是本来就没跑"。
接着看按文件读配置的接口。先看站点列表:
bash
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:9000/api/sites
# {"code":500,"message":"open /etc/nginx/sites-available: no such file or directory"}
再看主配置目录:
bash
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:9000/api/config
# {"code":500,"message":"stat /etc/nginx: no such file or directory"}
两条都是 500,报的还是同一类原因------/etc/nginx 不存在。这三条接口(/api/sites、/api/config、/api/streams)依赖真实的 Nginx 配置目录,本机没有就没有数据。这个报错方式其实挺好用:它明确告诉你缺的是哪个路径,而不是抛个泛泛的错误。落到你的服务器上,这两个接口应该返回你现有的站点与配置内容。
5.1 reload 前的语法校验,别跳过

图 2:
nginx -t两次结果对比------上栏正常配置给出成功提示,下栏缺分号的坏配置给出失败提示并带文件名与行号。
Nginx 那些让人心惊的 reload,绝大多数问题是"配置本来就有语法错"。所以改完配置的第一件事永远是:
bash
nginx -t
本机没有 nginx,为了把这一步做成确定性验证,我用容器里的真 nginx 跑了两轮。正常配置:
bash
mkdir -p /Users/admin/nginxui-verify/etc-nginx
docker run --rm nginx:alpine sh -c 'cat /etc/nginx/conf.d/default.conf' > etc-nginx/default.conf
printf 'server {\n listen 8088;\n server_name _;\n location / { return 200 "nginxui demo ok\\n"; }\n}\n' > etc-nginx/zz-site.conf
docker run --rm -v /Users/admin/nginxui-verify/etc-nginx:/etc/nginx/conf.d:ro nginx:alpine nginx -t
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful
再故意写坏------listen 后面少一个分号:
bash
printf 'server {\n listen 8089\n server_name _;\n}\n' > etc-nginx/zz-bad.conf
docker run --rm -v /Users/admin/nginxui-verify/etc-nginx:/etc/nginx/conf.d:ro nginx:alpine nginx -t
# [emerg] 1#1: invalid parameter "server_name" in /etc/nginx/conf.d/zz-bad.conf:3
# nginx: configuration file /etc/nginx/nginx.conf test failed
rm -f etc-nginx/zz-bad.conf
两种情况差别非常直观:正常时 test is successful,坏配置时 test failed,而且直接告诉你文件名和行号 (zz-bad.conf:3)。这就是"改完不敢 reload"的解药------先跑 nginx -t,它说 ok 再 reload,它说 failed 就按行号回去改。
踩坑记录:本机 Docker 走 colima(Ubuntu 24.04 VM + virtiofs),单文件 bind mount 和
/tmp(/private/tmp符号链接)路径会出现"挂载进去目录是空的、nginx -T不展开 site 片段"的现象。换成普通用户目录下的目录级挂载(/Users/admin/nginxui-verify/etc-nginx)就正常了。这是本机容器环境的路径限制,跟 Nginx-UI 无关,但你自己在 Mac 上做类似实验时也会碰到同样的坑。
5.2 Nginx-UI 的配置能力怎么落到你的服务器上
在你的真实服务器上(装了 nginx),Nginx-UI 对应的操作链路是:在面板里打开某个站点配置 → 编辑 → 保存时它会写入配置文件 → 然后你触发 reload。整个过程在界面上完成,不用 SSH。
其中"写回配置"这一步对应的底层接口,在 MCP 里就是下一节要讲的那些工具。这篇因为本机没有 nginx 配置目录,没有执行实际的配置写回 ,只验证了读取路径与 nginx -t 的前置校验流程。这一点我如实标注:配置写回需在真实 nginx 主机上补测。
6 接入 AI 助手:MCP 握手、12 个工具、先查后改
这一节是全文最有意思的部分,也是热点里最贴合的部分------让 AI 助手通过 MCP 来操作 Nginx。
6.1 MCP 端点默认拒绝匿名
Nginx-UI 内置 MCP 服务,端点是 /mcp(SSE)和 /mcp_message(消息投递)。先看它默认的安全姿态:
bash
curl -s -o /dev/null -w "HTTP %{http_code}\n" http://127.0.0.1:9000/mcp
# HTTP 403
curl -s -w "\nHTTP %{http_code}\n" -X POST \
"http://127.0.0.1:9000/mcp_message?sessionId=x" \
-H 'Content-Type: application/json' -d '{}'
# {"message":"Authorization failed"} HTTP 403
两个端点没有 Bearer token 都是 403。这个设计是对的------MCP 端点不能裸奔,因为它背后的工具能改配置、能 reload。谁拿到入口,谁就拿到了 Nginx 的操作权。
6.2 SSE 握手
带上管理员 JWT 连 SSE,会先收到一个 endpoint 事件:
bash
curl -s -N -H "Authorization: Bearer $TOKEN" -H "Accept: text/event-stream" \
http://127.0.0.1:9000/mcp
# event: endpoint
# data: /mcp_message?sessionId=d83caed0-512b-419f-8ea5-9d410e227caf
拿到 sessionId 后,往 /mcp_message?sessionId=... POST 标准 MCP 的 initialize,服务端回的 serverInfo 是:
json
{"name":"Nginx","version":"1.0.0"} protocolVersion: 2024-11-05
到这里握手就完成了。
6.3 tools/list:12 个工具

图 3:MCP SSE 握手时序------客户端先用 Bearer token 连 SSE 收到 endpoint 事件,再向消息投递地址发
initialize完成握手,最后请求tools/list拿到共 12 个工具。
接着请求 tools/list,服务端返回的能力清单如下(按响应原顺序):
| 工具名 | 作用 |
|---|---|
nginx_config_add |
新建配置文件 |
nginx_config_base_path |
查询配置根路径 |
nginx_config_enable |
启用配置(在 sites-enabled 建软链) |
nginx_config_get |
读取指定配置文件 |
nginx_config_history |
查看配置修改历史 |
nginx_config_list |
列出配置 |
nginx_config_mkdir |
新建目录 |
nginx_config_modify |
修改配置文件 |
nginx_config_rename |
重命名文件/目录 |
nginx_status |
查询 Nginx 状态 |
reload_nginx |
优雅 reload |
restart_nginx |
优雅 restart |
共 12 个。 顺带做个口径澄清:有些地方会看到"13 个工具"的说法,那是把 SSE 报文里 serverInfo 的 "name":"Nginx" 也一起数进去的结果(grep '"name":"' 会同时命中 serverInfo 和这 12 个工具)。以 tools/list 的响应为准,是 12 个。
我的自动化断言就卡在这一步:脚本里要求 tools/list 恰好返回 12 个,且必须包含 nginx_status、reload_nginx、nginx_config_get 这三个关键工具,缺一个就断言失败。实测全部通过。
6.4 这套工具怎么组成"安全改配置"的闭环
把这 12 个工具摆开,就能看出设计者给的动线:
- 先查 :
nginx_status看 Nginx 活没活,nginx_config_get/nginx_config_list读现有配置 - 再改 :
nginx_config_modify写回内容,nginx_config_add建新配置,nginx_config_enable建软链启用 - 留痕 :
nginx_config_history能看到某个文件改过什么 - 最后生效 :
reload_nginx触发优雅 reload
对应到实际使用,你自己配的 AI 助手可以按照这个顺序被约束:先读、给出修改建议、等你确认、再写、最后 reload。因为工具是分开的,你完全可以把"写入类"和"生效类"的调用权限拆开,让助手默认只能读,写和 reload 需要你授权。
提醒:这 12 个工具里,写回类和 reload 都是"有实际影响"的操作,建议只在自己的测试环境先跑通流程。生产服务器上,把助手的权限收到最窄------能读、能提建议就够,写和操作留给人来点。
6.5 客户端接入的现状与边界
MCP 客户端的接入方式是把 /mcp 端点和 Bearer token 填进你自己的 MCP 客户端配置里,握手协议就是标准的 initialize + tools/list,本机实测已完整走通。
但要如实说明一个边界:Nginx-UI 的 MCP Service Token 管理是在管理界面里交互式完成的,我这次没有通过 CLI 生成 token ,上面所有 MCP 调用都是用管理员 JWT 作为 Bearer 完成的。也就是说,"用独立的 MCP 专用 token(可以单独设权限、单独撤销)"这条路我这次是规划未实测------界面上有这个入口,但完整流程需要在界面上点一遍。你在服务器上落地时,建议优先走 MCP 专用 token,而不是长期用管理员 JWT。
7 用 cpolar 把面板短时开给自己
前面所有的验证都在本机。但如果我在外面,想用手机看一眼面板、或者让同事帮忙确认某个配置,就得有个公网入口。
Nginx-UI 的 9000 端口不能直接对公网开放(面板本身也没设计成公网服务,会话超时只有 10 分钟)。这时候用 cpolar 起一条临时隧道是最省事的做法------不开防火墙、不改路由,用完就关。
7.1 装 cpolar
macOS 走 Homebrew:
bash
brew tap probezy/core && brew install cpolar
sudo cpolar service install
sudo cpolar service start
装完验证服务状态:
bash
cpolar version
# cpolar version 3.3.18
curl -s -o /dev/null -w "HTTP %{http_code}\n" http://127.0.0.1:9200
# HTTP 200
9200 是 cpolar 的本地管理界面端口,能打开就说明服务在跑。
Linux 上用官方一键脚本更直接:
bash
curl -L https://www.cpolar.com/static/downloads/install-release-cpolar.sh | sudo bash
官方下载页在 download下载 - cpolar 极点云官网,各平台安装方式那页都有。
账号绑定有两条路:打开 http://127.0.0.1:9200 登录后,很多场景会自动把 token 写进配置;纯命令行环境也可以手动 cpolar authtoken xxx。token 在后台 cpolar - secure introspectable tunnels to localhost 页面里,标题是"你的隧道 Authtoken"。
7.2 建立隧道,拿到公网地址

图 4:cpolar 隧道建立后的日志示意------终端输出隧道已建立与公网地址占位符,HTTPS 临时入口就绪,用完即关。
因为 Nginx-UI 是网页服务,用 HTTP 隧道:
bash
cpolar http -log=stdout 9000
-log=stdout 让日志直接打到终端,方便看地址。建立成功的标志是这两行:
level=info msg="[:tunnel server module] Tunnel established at http://12f068a9.r3.nas.cpolar.cn"
level=info msg="[:tunnel server module] Tunnel established at https://12f068a9.r3.nas.cpolar.cn"
我这次跑出来的地址是 https://12f068a9.r3.nas.cpolar.cn,你以自己实际跑出来的为准。
拿到地址,先自己从公网探一下通不通:
bash
URL="https://12f068a9.r3.nas.cpolar.cn"
curl -s -m 25 -o /dev/null -w "HTTP %{http_code}\n" "$URL/healthz"
# HTTP 200
curl -s -m 25 -w "\nHTTP %{http_code}\n" "$URL/api/install"
# {"lock":false,"timeout":true}
# HTTP 200
公网地址上 /healthz 和 /api/install 都返回 200,说明这条链路已经打通------外面的人能打到你这台机器的 9000 端口了。
7.3 验收完立刻关隧道
这一步千万别忘。临时隧道是前台进程,它的生命周期就是你那条命令的生命周期。用完直接结束它:
bash
kill $(cat cpolar.pid)
然后复测同一个地址:
bash
curl -s -m 15 -o /dev/null -w "HTTP %{http_code}\n" "$URL/healthz"
# HTTP 404
返回 404,说明隧道已经断了、这个公网地址失效了。
提醒:免费档位给的是随机临时地址,24 小时内会变化,本身也不适合长期对外。如果你要一个固定入口(比如固定二级子域名),需要基础套餐或以上,那一步我这次未实测,属于规划中的扩展。
关于"短时开放"这件事,我把边界再明确一下:隧道打开的那段时间里,面板确实暴露在公网,登录保护就是 Nginx-UI 自己的 RSA 公钥加密登录 + 会话机制。所以正确的用法是随用随开、用完即关------只开你真正需要的那几分钟,而不是挂着一整天。
8 收尾:把暴露面收到最小
跑完这一趟,有几件事需要收尾,我按重要性排一下。
第一,令牌该撤就撤。 这次 MCP 调用用的是管理员 JWT,它是本次验证用的凭据。真实环境里应该创建独立的 MCP 专用 token,并且用完及时撤销------这样即使 token 泄露,影响面也被限死在 MCP 工具范围内,动不了账号本身。
第二,隧道确认关闭。 前面那条 kill 之后复测 404,就是这一条的验证。养成"开之前记下 PID、关之后复测一下"的习惯,避免以为关了其实还挂着。
第三,9000 端口不进防火墙白名单。 前面说过 Nginx-UI 默认监听全网卡,本地用没问题,但别顺手给它开个公网入站规则。公网入口只走 cpolar 这一层,职责才清晰。
第四,写操作先给测试机。 12 个工具里的 nginx_config_modify、nginx_config_enable、reload_nginx 都是会真实改动服务的,第一次用一定放到测试环境,把 AI 助手的权限压到"只能读 + 提建议",写和 reload 交给人点。
这套边界不复杂,但它决定了"让 AI 帮忙改 Nginx"这件事能不能放心做------你给助手的是受限的、可撤销的接口,而不是服务器的钥匙。
9 总结
到这里,一条"Nginx 配置可视化 + AI 助手受控接入 + 临时公网入口"的链路就跑通了:本机用 Nginx-UI v2.6.3 起来了面板,用 /healthz、/api/install 确认服务就绪,用 RSA 公钥登录拿到 JWT,读到了状态与配置接口,用容器里的真 nginx 验证了 nginx -t 正常与报错两种情况,通过 MCP SSE 握手列出了 12 个工具,最后用 cpolar 开了一条临时 HTTPS 隧道从公网访问面板并验收。
关键步骤:
- 起服务 :
./nginx-ui serve --config app.ini,/healthz返回 ok、/api/install返回 200 且lock=false,lsof确认 9000 已绑定 - 接助手 :
/mcp拿 endpoint →/mcp_message走initialize+tools/list,返回 12 个工具,含nginx_status/reload_nginx/nginx_config_get;MCP 端点无 token 一律 403 - 保安全 :改配置前先
nginx -t(正常test is successful,写坏则test failed并给出文件名行号),cpolar 隧道用完即关,复测返回 404
后续扩展的方向也清楚:本机没有 nginx,所以 /api/sites、/api/config 这类接口报 500------在真实 nginx 主机上补齐配置目录后,就能把"读配置 → AI 给建议 → 写回 → 校验 → reload"这整条动线走完整。再往前一步,是给 MCP 配一个独立的、可撤销的专用 token,把助手权限收到最小,顺手给 cpolar 配个固定二级子域名当长期入口。省事之处在于------你不再需要 SSH 上去 vi 一个配置文件然后心跳加速地 reload,而是先看、先校验、再决定,主动权一直在你自己手里。
附:验证环境与实测说明
- 主机:macOS 14.5 (23F79) arm64;Go 运行时 go1.27.1;Docker 客户端 29.5.2(colima VM 29.2.1);cpolar 3.3.18
- Nginx-UI:v2.6.3(
nginx-ui 2.6.3 3(566) 826c6fae (go1.27.1 darwin/arm64)),监听[::]:9000 - 验证:全部 CLI / HTTP 确定性断言,共 19 项全部通过(脚本与日志见
articles/tests/topic-20260922-inventory-backfill-b2-001/) - 关键断言:
/healthz={"status":"ok"}、/api/install= 200 且lock=false、MCPtools/list= 12 个工具、nginx -t正常/异常两种结果、cpolar 公网/healthz= 200 且关闭后 = 404 - cpolar 公网地址为免费档位随机临时地址,验收完成后隧道已终止,该地址不再有效
- 未实测(如实标注):本机未装 nginx,
/api/sites、/api/config、/api/streams返回 500,需在真实 nginx 主机补测;配置写回类 MCP 工具未实际执行;MCP Service Token 的创建与撤销为界面交互流程,未走 CLI;cpolar 固定二级子域名、持久后台隧道、ACME 证书签发未实测 - 全文只在本机自建环境演示,未接入任何真实生产服务器、真实域名或真实证书,不含任何可用凭据,也不提供任何规避安全限制的做法