Skip to main content
Glama
linuskang

nginx-proxy-manager-mcp

by linuskang

nginx-proxy-manager-mcp

License: CC BY-NC 4.0 Node TypeScript 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.com at 192.168.1.50:3000 and 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 passthroughnpm_raw_request for anything not covered

  • 30 tools total, all typed with JSON schemas for reliable agent use

  • Two transportsstdio (default, for local agents) and Streamable http

  • No 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 build

Or run directly without cloning (npx once published):

npx nginx-proxy-manager-mcp

2. Configure

Copy .env.example.env and fill in your NPM admin credentials:

cp .env.example .env

Variable

Required

Description

NPM_BASE_URL

Base URL of NPM, e.g. http://npm.local:81 (no trailing slash)

NPM_EMAIL

*

Admin email (NPM_TOKEN alternative)

NPM_PASSWORD

*

Admin password (NPM_TOKEN alternative)

NPM_TOKEN

*

Pre-existing JWT token (takes precedence over email/password)

NPM_TIMEOUT_MS

Request timeout, default 30000

NPM_DEBUG

Verbose stderr logging, default false

MCP_TRANSPORT

stdio (default) or http

MCP_PORT

HTTP port, default 3000

MCP_HOST

HTTP bind address, default 0.0.0.0

MCP_ENDPOINT

HTTP endpoint path, default /mcp

* 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/mcp

Available tools (30)

Proxy hosts

Tool

Description

npm_list_proxy_hosts

List all reverse proxies

npm_get_proxy_host

Get one by id

npm_create_proxy_host

Create a reverse proxy (the headline tool)

npm_update_proxy_host

Update fields on an existing proxy

npm_delete_proxy_host

Delete by id

npm_enable_proxy_host

Enable a disabled proxy

npm_disable_proxy_host

Disable a proxy (without deleting)

Streams (TCP/UDP port forwarding)

Tool

Description

npm_list_streams

List all streams

npm_get_stream

Get one by id

npm_create_stream

Create a TCP/UDP port forward

npm_update_stream

Update a stream

npm_delete_stream

Delete a stream

Redirection hosts

Tool

Description

npm_list_redirection_hosts

List redirections

npm_create_redirection_host

Create a redirect (301/302)

npm_update_redirection_host

Update a redirect

npm_delete_redirection_host

Delete a redirect

Dead (404) hosts

Tool

Description

npm_list_dead_hosts

List 404 hosts

npm_create_dead_host

Create a 404 host

npm_update_dead_host

Update a 404 host

npm_delete_dead_host

Delete a 404 host

Certificates (Let's Encrypt & custom)

Tool

Description

npm_list_certificates

List all certificates

npm_create_certificate

Request a new Let's Encrypt cert (HTTP-01 or DNS-01)

npm_renew_certificate

Renew an existing cert

npm_delete_certificate

Delete a certificate

npm_download_certificate

Download cert / private key / chain (PEM)

Users, audit & power tools

Tool

Description

npm_ping

Health check the NPM instance

npm_list_users

List NPM users

npm_get_user

Get a user by id

npm_list_audit_log

Browse recent audit log entries

npm_raw_request

Authenticated escape hatch to any /api/... endpoint

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.com192.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:latest

Image 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:latest

MCP 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 -d

Logs:

docker compose logs -f

Stop / remove:

docker compose down

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 container

Then 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-mcp

Troubleshooting

  • npm:54 / connection refused on port 81NPM_BASE_URL must 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_TOKEN to fall back to email/password auto-refresh, or regenerate the token from the NPM UI.

  • Want to debug requests? Set -e NPM_DEBUG=true to 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:check

Project 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       # aggregator

Compatibility

  • 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_DEBUG is 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.

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

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