npm-mcp
npm-mcp
用于 Nginx Proxy Manager 的 Model Context Protocol 服务器
以对话方式管理反向代理路由、TLS 证书、访问列表和流转发——并带有护栏,假设你最终会将其指向生产环境。
目录
Related MCP server: npm-mcp
为什么存在
Nginx Proxy Manager 有完整的 REST API,但没有 MCP 服务器。这就是那个服务器——但有趣的部分不是管道,而是约束。
反向代理是其背后所有服务的单点故障。一个拥有写权限的代理可以关闭它从未被要求触及的服务。因此设计从这一点出发:
工具是从 API 自身的 OpenAPI 文档生成的,而非手写。 文档被固定在树内,漂移测试会在上游接口变化时使 CI 失败——而不是让工具在运行时静默 404。
每个结果都经过一个失败关闭的脱敏边界。 它会对任何无法检查的内容抛出异常,而不是直接传递。
护栏经过变异测试。 每个安全控制都有一个测试,证明当控制被禁用时会变红。
工作原理
flowchart LR
C["MCP Client"] -->|"Bearer (optional)"| S
subgraph S["npm-mcp"]
direction TB
A["Bearer verifier<br/><i>hmac.compare_digest</i>"] --> G["Guardrails<br/><i>S1 · S2 · S6 · S7 · S8</i>"]
G --> T["66 generated tools"]
T --> R["serialize_result()<br/><i>redact + cap</i>"]
end
S -->|"JWT, auto-refreshed"| N["Nginx Proxy Manager"]
P["npm-openapi.json<br/><i>pinned, in-package</i>"] -.->|generates| T工具签名在导入时从固定的文档构建,因此 create_proxy_host 暴露了 18 个带真实枚举的类型化参数——而不是一个不透明的 **kwargs 传递。
快速开始
uv sync
cp .env.example .env # then fill in NPM_URL / NPM_IDENTITY / NPM_SECRET
uv run npm-mcp{
"mcpServers": {
"npm": {
"command": "uv",
"args": ["run", "npm-mcp"],
"env": {
"NPM_URL": "https://nginx-proxy-manager.example.net",
"NPM_IDENTITY": "npm-mcp@example.net",
"NPM_SECRET": "…",
"NPM_MCP_TRANSPORT": "stdio"
}
}
}
}{
"mcpServers": {
"npm": {
"type": "http",
"url": "https://npm-mcp.example.net/mcp",
"headers": { "Authorization": "Bearer <NPM_MCP_BEARER_TOKEN>" }
}
}
}FastMCP 在 /mcp 提供服务。尾部斜杠会 307 重定向,某些客户端处理不当——不要让代理重写路径。
[!TIP] 首先调用
get_guidance。它会报告响应形状、禁用与删除的区别、当前哪些锁已打开,以及当前受保护的域名列表。
认证
两层,容易混淆:
方向 | 机制 | |
入站 | 客户端 → npm-mcp | 可选的 |
出站 | npm-mcp → NPM | 账户凭据 → 短期 JWT,自动刷新。调用者永远看不到或提供它。 |
NPM 不颁发长期 API 密钥,这就是服务器持有凭据而不是接受令牌的原因。
[!IMPORTANT]
POST /tokens有 两种 可能的响应:一个令牌,或一个 2FA 挑战。 如果账户启用了 2FA,请设置NPM_TOTP_SECRET——否则服务器会 在启动时 失败,并指出两种补救措施,而不是启动后正常但在第一次工具调用时崩溃。
工具目录
66 个工具 = 65 个 API 操作 + get_guidance。
家族 | # | 代表性工具 |
🔀 代理主机 | 7 |
|
↪️ 重定向主机 | 7 |
|
🚫 404 主机 | 7 |
|
🔌 流 | 7 |
|
🔐 访问列表 | 5 |
|
📜 证书 | 10 |
|
👤 用户 | 8 |
|
🔑 用户 2FA | 5 |
|
⚙️ 设置 | 3 |
|
📋 审计日志 | 2 |
|
ℹ️ 元信息 | 4 |
|
🧭 指导 | 1 |
|
名称源自 OpenAPI operationId,因此列表操作是 get_*,而不是 list_*。
[!WARNING] 三个操作被有意不暴露:
requestToken、refreshToken、loginWith2FA。它们是服务器自身的认证管道,而requestToken接受 任意 身份和密钥——注册它会把此服务器变成针对 NPM 的凭据测试预言机,每次尝试都归因于服务账户。
不存在分页。 没有一个端点接受
limit/offset。工具接受它们并在 客户端 进行切片;工具描述中说明了这一点。expand是每个端点的枚举,不是传递——代理主机接受access_list,owner,certificate;证书只接受owner。超出枚举的值会在请求发送前被拒绝。
安全模型
[!CAUTION] 写入默认启用。 此服务器可以重写代理背后每个服务的路由表。设置
NPM_READ_ONLY=1以禁用所有变更。
控制 | 覆盖 | |
| 拒绝所有变更工具,在任何护栏读取之前检查 | — |
S1 | 拒绝在受保护主机上执行 |
|
S2 | 每个 | 每次调用 |
S5 | 每次变更都会产生一条审计行;NPM 自身的审计日志可查询 | — |
S6 |
|
|
S7 | 拒绝修改、禁用、删除或 | 无 |
S8 |
|
|
S1 匹配 ANY 受保护域名,而不是 ALL。 ALL 会让护栏通过它所保护的 工具 被解除:向主机添加一个无关域名,保护就会消失。
S1 覆盖
update,而不仅仅是 delete/disable。 否则你可以从domain_names中剥离受保护的名称,然后干净地删除——同样的中断。S1 匹配当前上游状态,绝不匹配提交的请求体。 检查请求会让剥离-然后-更新路径直接通过。
S1 通配符双向匹配。
NPM_PROTECTED_DOMAINS=*.example.net必须保护app.example.net。它曾经匹配不到任何内容 并且 抑制了“未受保护”的警告,因为该值被显式设置。S2 按 HTTP 方法限定范围,而不是名称前缀。
delete_*规则会漏掉disable_user_2fa——一个DELETE会剥离某人的第二因素。S6 是规则,不是列表。 枚举版本静默遗漏了
update_user,因此锁存器保持关闭,而is_disabled: true锁定了管理员。S7 没有覆盖。 一个能删除自身凭据的服务器会永久锁定自己。
配置
变量 | 含义 |
| NPM 实例的基础 URL |
| 账户邮箱 |
| 账户密码 |
变量 | 默认值 | 含义 |
| 未设置 | 入站令牌。未设置 ⇒ 无入站认证 |
|
|
|
|
| 绑定地址 |
|
| 绑定端口 |
变量 | 默认值 | 提升条件 |
|
| —( |
| 派生自 | S1 拒绝列表,逗号分隔 |
|
| S1 |
|
| S6 |
|
| S8 |
变量 | 默认值 | 含义 |
| 未设置 | Base32 种子;仅当账户启用了 2FA 时 |
|
| 验证 NPM 的证书 |
|
| 上游超时,秒 |
|
| 截断前的响应上限 |
|
| 在早期变更时提示使用 |
|
|
部署
docker build -t npm-mcp:latest .
docker compose up -d容器加入一个现有的 Docker 网络,与 NPM 同处其中,并且不发布任何端口。NPM 通过容器 DNS 访问它并终止 TLS,因此 Bearer 令牌永远不会以明文形式在网络上传输。
compose 文件中没有
build:键。 compose-字符串部署(例如 Portainer)不会携带构建上下文,因此镜像需要先构建好,再通过标签引用。健康检查解析绑定主机,而不是硬编码
127.0.0.1。当使用自定义的NPM_MCP_HTTP_HOST时,朴素的写法会把一个完全健康的容器永远标记为不健康。它在stdio下也会短路,因为那里根本没有服务在监听。认证预热在服务器生命周期内运行,因此配置错误会直接导致健康检查失败,而不是先显示为绿色、然后在首次使用时才崩溃。
测试
uv run pytest # 420 tests
uv run ruff check
uv run ruff format --check大约 4,700 行测试对应 3,300 行源码,但数量不如形态重要:
🧬 经变异验证的护栏 —— 每个安全控制都有一项测试,证明当该控制被禁用时测试会失败。这是在发现一个
asyncio.Lock被移除后测试套件仍然全绿之后编写的。🌐 零网络访问 —— 每次上游调用都用
respx模拟。需要网络的测试就是有问题的测试。🔍 A7 扫描 —— 全部 65 个工具都会针对一个在四个嵌套深度返回秘密的上游进行调用,并带有一个阴性对照,断言测试夹具确实包含这些秘密,从而确保扫描不会空洞地通过。
📐 模式漂移防护 —— 操作数量、载荷形状和打包的数据文件都有断言,因此上游升级会在这里失败,而不是在生产环境中失败。
设计说明
文档 | 内容 |
产品契约 —— 决策 D1–D13、控制 S1–S8、验收标准 A1–A10 | |
全部 68 个操作及其请求体字段和必填性 | |
内部模块接口 | |
OpenAPI 文档中两处错误之处,已对照真实实例进行验证 | |
实例 |
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityCmaintenanceEnables management of Nginx Proxy Manager instances for configuring proxy hosts, requesting Let's Encrypt SSL certificates, and managing access lists. It allows users to control their web proxy infrastructure through natural language commands in MCP-compatible environments.503MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage Nginx Proxy Manager instances through natural language, covering 28 tools for proxy hosts, certificates, streams, and more.MIT
- AlicenseCqualityDmaintenanceMCP server that abstracts the Nginx Proxy Manager API, enabling management of proxy hosts, redirections, streams, certificates, access lists, and users through natural language.54171AGPL 3.0
- AlicenseAqualityAmaintenanceEnables natural language management of FastPanel 2 servers, including creating sites, databases, SSL certificates, and hardening nginx configurations.322MIT
Related MCP Connectors
Let AI operate servers without SSH. Choose actions, approve risky changes, and audit every step.
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/omichelbraga/nginx-proxy-manager-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server