nginx-proxy-manager-mcp
Allows requesting and managing Let's Encrypt SSL/TLS certificates for proxy hosts via HTTP-01 or DNS-01 challenges.
Provides tools for managing Nginx Proxy Manager, including creating and managing proxy hosts, streams, redirection hosts, 404 hosts, and Let's Encrypt certificates.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@nginx-proxy-manager-mcpPoint myapp.example.com to 192.168.1.100:8080 with SSL"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
nginx-proxy-manager-mcp
A Model Context Protocol server that exposes the Nginx Proxy Manager (NPM) REST API to AI agents. Let assistants like Claude Desktop, Hermes, Cursor, or any MCP-compatible client create reverse proxies, TCP/UDP streams, redirects, 404 hosts, and request/renew Let's Encrypt certificates for you — in plain English.
"Hey Hermes, point
grafana.example.comat192.168.1.50:3000and get a Let's Encrypt cert for it." →npm_create_proxy_host+npm_create_certificate+npm_update_proxy_host
Features
Proxy hosts — create / list / update / delete / enable / disable reverse proxies
Streams — TCP & UDP port forwarding
Redirection hosts — domain → domain redirects (301/302)
Dead (404) hosts — return 404 for parked/unused domains
Certificates — request Let's Encrypt (HTTP-01 or DNS-01), renew, delete, download
Users & audit log — inspect users and recent actions
Raw passthrough —
npm_raw_requestfor anything not covered30 tools total, all typed with JSON schemas for reliable agent use
Two transports —
stdio(default, for local agents) and StreamablehttpNo runtime deps besides the official MCP SDK + zod
Related MCP server: Nginx Proxy Manager MCP
Quick start
1. Install
git clone https://github.com/linuskang/nginx-proxy-manager-mcp.git
cd nginx-proxy-manager-mcp
npm install
npm run buildOr run directly without cloning (npx once published):
npx nginx-proxy-manager-mcp2. Configure
Copy .env.example → .env and fill in your NPM admin credentials:
cp .env.example .envVariable | Required | Description |
| ✅ | Base URL of NPM, e.g. |
| ✅* | Admin email ( |
| ✅* | Admin password ( |
| ✅* | Pre-existing JWT token (takes precedence over email/password) |
| ❌ | Request timeout, default |
| ❌ | Verbose stderr logging, default |
| ❌ |
|
| ❌ | HTTP port, default |
| ❌ | HTTP bind address, default |
| ❌ | HTTP endpoint path, default |
* Provide either NPM_TOKEN or both NPM_EMAIL + NPM_PASSWORD.
3. Wire it up to your agent
Claude Desktop (or Claude Code)
Edit claude_desktop_config.json (macOS:
~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"nginx-proxy-manager": {
"command": "node",
"args": ["D:/Code/Git/nginx-proxy-manager-mcp/dist/index.js"],
"env": {
"NPM_BASE_URL": "http://npm.local:81",
"NPM_EMAIL": "[email protected]",
"NPM_PASSWORD": "your-password",
},
},
},
}Hermes
In your Hermes agent config (or MCP registry), add a server entry pointing at the
same command/env above. Hermes speaks standard MCP over stdio, so no special
setup is needed — just point it at node dist/index.js with your NPM_* env.
Remote / HTTP transport (browser agents, remote runners)
MCP_TRANSPORT=http MCP_PORT=3000 MCP_HOST=0.0.0.0 node dist/index.js
# POST your JSON-RPC messages to http://localhost:3000/mcpAvailable tools (30)
Proxy hosts
Tool | Description |
| List all reverse proxies |
| Get one by id |
| Create a reverse proxy (the headline tool) |
| Update fields on an existing proxy |
| Delete by id |
| Enable a disabled proxy |
| Disable a proxy (without deleting) |
Streams (TCP/UDP port forwarding)
Tool | Description |
| List all streams |
| Get one by id |
| Create a TCP/UDP port forward |
| Update a stream |
| Delete a stream |
Redirection hosts
Tool | Description |
| List redirections |
| Create a redirect (301/302) |
| Update a redirect |
| Delete a redirect |
Dead (404) hosts
Tool | Description |
| List 404 hosts |
| Create a 404 host |
| Update a 404 host |
| Delete a 404 host |
Certificates (Let's Encrypt & custom)
Tool | Description |
| List all certificates |
| Request a new Let's Encrypt cert (HTTP-01 or DNS-01) |
| Renew an existing cert |
| Delete a certificate |
| Download cert / private key / chain (PEM) |
Users, audit & power tools
Tool | Description |
| Health check the NPM instance |
| List NPM users |
| Get a user by id |
| Browse recent audit log entries |
| Authenticated escape hatch to any |
Example: create a proxy host
// npm_create_proxy_host
{
"domain_names": ["grafana.example.com"],
"forward_scheme": "http",
"forward_host": "192.168.1.50",
"forward_port": 3000,
"block_exploits": true,
"allow_websocket_upgrade": true,
"certificate_id": 0,
"ssl_forced": false,
"enabled": true,
}A natural-language request like "Proxy grafana.example.com → 192.168.1.50:3000
with a Let's Encrypt cert" will typically run npm_create_proxy_host, then
npm_create_certificate (provider letsencrypt), then
npm_update_proxy_host with the returned certificate_id and ssl_forced: true.
Deploying with Docker
A prebuilt multi-arch image (linux/amd64 + linux/arm64) is published to the
GitHub Container Registry on every push to main/master and on version tags:
docker pull ghcr.io/linuskang/nginx-proxy-manager-mcp:latestImage tags: latest, :vX.Y.Z, :X.Y, :X, :sha-<short>, :master.
Which transport? Use stdio when the agent runs on the same machine (Claude Desktop, Hermes, Cursor) and you launch the container as a child process. Use http when a remote agent or browser client needs to POST JSON-RPC over the network.
Option A — stdio (local agent on the same machine)
Your agent config launches the container and speaks MCP over its stdin/stdout.
Point the agent's command at docker and pass run -i --rm plus the env vars:
// Claude Desktop / Hermes MCP server config
{
"mcpServers": {
"nginx-proxy-manager": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"NPM_BASE_URL",
"-e",
"NPM_EMAIL",
"-e",
"NPM_PASSWORD",
"ghcr.io/linuskang/nginx-proxy-manager-mcp:latest",
],
"env": {
"NPM_BASE_URL": "http://your-npm-host:81",
"NPM_EMAIL": "[email protected]",
"NPM_PASSWORD": "your-password",
},
},
},
}-i keeps stdin open so the agent can talk to the server; --rm cleans up the
container when the agent exits. No port is published because stdio doesn't need
one. Transport defaults to stdio, so you don't have to set MCP_TRANSPORT.
Option B — HTTP (remote / networked agents)
Expose a Streamable HTTP endpoint that any MCP client can POST to:
docker run -d --name npm-mcp \
-p 3000:3000 \
-e MCP_TRANSPORT=http \
-e MCP_PORT=3000 \
-e MCP_HOST=0.0.0.0 \
-e NPM_BASE_URL=http://your-npm-host:81 \
-e [email protected] \
-e NPM_PASSWORD=your-password \
ghcr.io/linuskang/nginx-proxy-manager-mcp:latestMCP endpoint: http://localhost:3000/mcp
Verify it's up:
curl -s http://localhost:3000/mcp -X POST \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'You should get a JSON-RPC response with serverInfo.name == "nginx-proxy-manager-mcp".
Point your agent at the URL and it will initialize, call tools/list, and
start driving your NPM instance.
Option C — docker compose
For a persistent HTTP deployment, use the bundled docker-compose.yml:
cp .env.example .env
# edit .env: set NPM_BASE_URL, NPM_EMAIL, NPM_PASSWORD,
# MCP_TRANSPORT=http, MCP_PORT=3000, MCP_HOST=0.0.0.0
docker compose up -dLogs:
docker compose logs -fStop / remove:
docker compose downPutting NPM and the MCP server on the same Docker network (recommended)
If Nginx Proxy Manager itself runs in Docker, put the MCP container on the same network so you can address NPM by service name — no published ports needed:
docker network create npm-net
docker network connect npm-mcp npm-net # if MCP created its own net
docker network connect <npm-container> npm-net # for the NPM containerThen set NPM_BASE_URL=http://<npm-service-name>:81 (e.g. http://npm:81) and
the MCP server talks to NPM over the private bridge.
Build locally (optional, same Dockerfile used by CI)
docker build -t nginx-proxy-manager-mcp .
# stdio:
docker run -i --rm \
-e NPM_BASE_URL=http://npm:81 -e NPM_EMAIL=a@b.c -e NPM_PASSWORD=secret \
nginx-proxy-manager-mcp
# http:
docker run -d -p 3000:3000 \
-e MCP_TRANSPORT=http -e MCP_PORT=3000 -e MCP_HOST=0.0.0.0 \
-e NPM_BASE_URL=http://npm:81 -e NPM_EMAIL=a@b.c -e NPM_PASSWORD=secret \
nginx-proxy-manager-mcpTroubleshooting
npm:54/ connection refused on port 81 —NPM_BASE_URLmust point at the admin API port (81), not 80/443. If NPM is in another container, use the service name and a shared Docker network.NPM_TOKEN or both NPM_EMAIL and NPM_PASSWORD must be set— provide either a JWT (NPM_TOKEN) or an email + password pair.Tools call returns HTTP 401 — your token expired or the credentials are wrong. Remove
NPM_TOKENto fall back to email/password auto-refresh, or regenerate the token from the NPM UI.Want to debug requests? Set
-e NPM_DEBUG=trueto log every request URL to stderr (docker logs -f npm-mcp).
Development
npm install # install deps
npm run dev # run from source (tsx)
npm run build # compile to dist/
npm run typecheck # typecheck only
npm run lint # eslint
npm run format # prettier write
npm run check # lint + typecheck + format:checkProject layout:
src/
config.ts # env-based configuration
types.ts # NPM API TypeScript types
client.ts # NPM REST client (auth, retry, JSON)
index.ts # MCP server + stdio/http transports
tools/
_shared.ts # tool helpers (ok/fail/guard)
proxy-hosts.ts
streams.ts
redirection-hosts.ts
dead-hosts.ts
certificates.ts
misc.ts # ping, users, audit, raw request
index.ts # aggregatorCompatibility
Nginx Proxy Manager 2.x (REST API on port 81)
Node.js ≥ 18 (uses global
fetch,AbortSignal.timeout)MCP protocol version 2024-11-05 and later
Security notes
Credentials are passed via environment variables only — never logged unless
NPM_DEBUGis on (and even then, only request URLs, never the password).The exposed tools use your NPM admin token, so they can do anything an admin can. Run this server in a trusted environment and restrict network exposure.
Prefer scoped NPM users if your deployment supports it.
Contributing
PRs welcome! Please open an issue first for larger changes. Run npm run check
before submitting. See CONTRIBUTING.md.
License
Licensed under Creative Commons Attribution-NonCommercial 4.0 International
(CC BY-NC 4.0) — see
LICENSE. You are free to share and adapt for non-commercial
purposes with attribution. Commercial use requires a separate license from the
author.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- 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/linuskang/nginx-proxy-manager-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server