Skip to main content
Glama

npm-mcp

Nginx Proxy Manager용 Model Context Protocol 서버

대화형으로 리버스 프록시 라우팅, TLS 인증서, 접근 목록, 스트림 포워드를 관리하세요 — 언젠가 프로덕션을 대상으로 삼을 것을 전제로 한 안전장치가 함께 제공됩니다.

Python FastMCP NPM Tests Tools Ruff


목차


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는 불투명한 **kwargs 전달이 아닌 실제 열거형을 가진 18개의 타입이 지정된 인자를 노출합니다.


빠른 시작

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_BEARER_TOKEN을 통한 선택적 Authorization: Bearer …, hmac.compare_digest로 비교. 미설정 ⇒ 인증 없음.

아웃바운드

npm-mcp → NPM

계정 자격 증명 → 단기 JWT, 자동 갱신. 호출자는 이를 볼 수도 제공할 수도 없음.

NPM은 장기 API 키를 발급하지 않으므로, 서버가 토큰을 받는 대신 자격 증명을 보관합니다.

[!IMPORTANT] POST /tokens에는 두 가지 가능한 응답이 있습니다: 토큰 또는 2FA 챌린지. 계정에 2FA가 활성화되어 있으면 NPM_TOTP_SECRET을 설정하세요 — 그렇지 않으면 서버는 시작 시 실패하며 두 가지 해결책을 모두 명시하고, 정상으로 뜬 뒤 첫 도구 호출에서 깨지지 않습니다.


도구 카탈로그

66개 도구 = 65개 API 작업 + get_guidance.

계열

#

대표 도구

🔀 프록시 호스트

7

get_proxy_hosts · create_proxy_host · update_proxy_host · delete_proxy_host · enable_proxy_host · disable_proxy_host

↪️ 리다이렉션 호스트

7

*_redirection_host

🚫 404 호스트

7

create_404_host · *_dead_host

🔌 스트림

7

*_stream

🔐 접근 목록

5

get_access_lists · create_access_list · update_access_list · delete_access_list

📜 인증서

10

get_certificates · create_certificate · renew_certificate · upload_certificate · validate_certificates · download_certificate · test_http_reach · get_dns_providers

👤 사용자

8

get_users · create_user · update_user · update_user_auth · update_user_permissions · login_as_user

🔑 사용자 2FA

5

setup_user_2fa · enable_user_2fa · disable_user_2fa · get_user_2fa_status · regen_user_2fa_codes

⚙️ 설정

3

get_settings · update_setting

📋 감사 로그

2

get_audit_logs · get_audit_log

ℹ️ 메타

4

health · check_version · reports_hosts · schema

🧭 안내

1

get_guidance

이름은 OpenAPI operationId에서 파생되므로 목록 작업은 list_*가 아닌 get_*입니다.

[!WARNING] 세 가지 작업은 의도적으로 노출되지 않습니다: requestToken, refreshToken, loginWith2FA. 이들은 서버 자체의 인증 배관이며, requestToken임의의 신원과 비밀번호를 허용합니다 — 이를 등록하면 이 서버가 NPM에 대한 자격 증명 테스트 오라클로 변하고, 모든 시도가 서비스 계정에 귀속됩니다.

  • 페이지네이션이 없습니다. limit/offset을 허용하는 엔드포인트가 하나도 없습니다. 도구는 이를 허용하고 클라이언트 측에서 슬라이스합니다. 도구 설명에 그렇게 명시되어 있습니다.

  • expand는 엔드포인트별 열거형이며, 전달이 아닙니다 — 프록시 호스트는 access_list,owner,certificate를 받고, 인증서는 owner만 받습니다. enum 밖의 값은 요청 전에 거부됩니다.


안전 모델

[!CAUTION] 쓰기는 기본적으로 활성화되어 있습니다. 이 서버는 프록시 뒤의 모든 서비스에 대한 라우팅 테이블을 재작성할 수 있습니다. 모든 변형을 비활성화하려면 NPM_READ_ONLY=1을 설정하세요.

제어

재정의

NPM_READ_ONLY

모든 변형 도구를 거부하며, 안전장치 읽기보다 먼저 확인됨

S1

보호된 호스트와 해당 호스트가 의존하는 인증서 및 접근 목록에 대한 delete / disable / update 를 거부함

NPM_ALLOW_SELF_MUTATION

S2

모든 DELETEconfirm: true를 요구함; 없으면 도구는 영향을 받을 내용을 반환하고 아무것도 쓰지 않음

호출별

S5

모든 변형은 감사 라인 하나를 생성함; NPM 자체 감사 로그는 쿼리 가능함

S6

/users 또는 /settings 아래의 모든 변형 작업은 래치됨

NPM_ALLOW_ACCOUNT_MUTATION

S7

자체 계정의 수정, 비활성화, 삭제 또는 login_as를 거부함

없음

S8

download_certificate는 TLS 개인 키를 반환하므로 래치됨

NPM_ALLOW_CERT_EXPORT

  • S1은 보호된 도메인 중 ANY와 일치하며, ALL이 아닙니다. ALL은 보호하는 도구를 통해 안전장치가 무장 해제될 수 있게 합니다: 호스트에 무관한 도메인 하나를 추가하면 보호가 사라집니다.

  • S1은 delete/disable뿐 아니라 update도 포함합니다. 그렇지 않으면 domain_names에서 보호된 이름을 제거한 후 깨끗하게 삭제할 수 있습니다 — 동일한 중단이 발생합니다.

  • S1은 제출된 본문이 아닌 현재 업스트림 상태와 일치합니다. 요청을 확인하면 제거 후 업데이트 경로가 그대로 통과할 수 있습니다.

  • S1 와일드카드는 양방향으로 일치합니다. NPM_PROTECTED_DOMAINS=*.example.netapp.example.net을 보호해야 합니다. 한때 아무것도 일치하지 않았고, 값이 명시적으로 설정되어 있었기 때문에 "보호되지 않음" 경고도 억제했습니다.

  • S2는 이름 접두사가 아닌 HTTP 메서드로 범위를 지정합니다. delete_* 규칙은 disable_user_2fa를 놓칩니다 — 이는 누군가의 2차 인증을 제거하는 DELETE입니다.

  • S6은 목록이 아닌 규칙입니다. 열거형 버전은 update_user를 조용히 누락시켜, is_disabled: true가 관리자를 잠그는 동안 래치가 닫힌 상태로 유지되었습니다.

  • S7에는 재정의가 없습니다. 자체 자격 증명을 삭제할 수 있는 서버는 영구적으로 잠깁니다.


설정

변수

의미

NPM_URL

NPM 인스턴스의 기본 URL

NPM_IDENTITY

계정 이메일

NPM_SECRET

계정 비밀번호

변수

기본값

의미

NPM_MCP_BEARER_TOKEN

미설정

인바운드 토큰. 미설정 ⇒ 인바운드 인증 없음

NPM_MCP_TRANSPORT

streamable-http

stdio | streamable-http

NPM_MCP_HTTP_HOST

0.0.0.0

바인드 주소

NPM_MCP_HTTP_PORT

8000

바인드 포트

변수

기본값

해제 조건

NPM_READ_ONLY

0

— (1은 모든 쓰기를 차단)

NPM_PROTECTED_DOMAINS

NPM_URL에서 파생

S1 차단 목록, 쉼표로 구분

NPM_ALLOW_SELF_MUTATION

0

S1

NPM_ALLOW_ACCOUNT_MUTATION

0

S6

NPM_ALLOW_CERT_EXPORT

0

S8

변수

기본값

설명

NPM_TOTP_SECRET

미설정

Base32 시드. 계정에 2FA가 설정된 경우에만 사용

NPM_TLS_VERIFY

1

NPM 인증서 검증

NPM_TIMEOUT

30

업스트림 타임아웃(초)

NPM_MAX_RESPONSE_CHARS

50000

잘림이 적용되기 전의 응답 상한

NPM_GUIDANCE_GATE

1

초기 변형 시 get_guidance를 안내

LOG_LEVEL

INFO


배포

docker build -t npm-mcp:latest .
docker compose up -d

컨테이너는 NPM과 나란히 기존 Docker 네트워크에 연결되며 포트를 전혀 공개하지 않습니다. NPM은 컨테이너 DNS로 해당 컨테이너에 접근하고 TLS를 종료하므로, Bearer 토큰이 평문으로 네트워크를 통과하지 않습니다.

  • compose 파일에 build: 키가 없습니다. compose-문자열 배포(예: Portainer)는 빌드 컨텍스트를 포함하지 않으므로, 이미지를 먼저 빌드한 뒤 태그로 참조합니다.

  • healthcheck는 127.0.0.1을 하드코딩하는 대신 바인드 호스트를 해석합니다. 커스텀 NPM_MCP_HTTP_HOST를 사용하면 단순한 버전은 완전히 정상인 컨테이너를 영원히 비정상으로 표시합니다. 또한 stdio에서는 리슨 중인 것이 아무것도 없으므로 아예 동작하지 않게 됩니다.

  • 인증 워밍업은 서버 수명주기에서 실행됩니다. 따라서 구성이 잘못되면 처음 사용했을 때 문제를 일으키기보다는 이미 healthcheck에서 실패하게 됩니다.


테스트

```bash

uv run pytest # 420 tests uv run ruff check uv run ruff format --check


대략 **테스트 4,700줄과 소스 3,300줄**이지만, 수치보다 중요한 것은 구성입니다:

* 🧬 **변이 검증 안전장치** — 모든 안전 제어에는 해당 제어를 비활성화했을 때 실패하는 테스트가 있습니다. 제거해도 테스트가 그대로 통과하는 `asyncio.Lock`을 발견한 뒤 작성했습니다.
* 🌐 **네트워크 접근 제로** — 외부 호출은 전부 `respx`로 모킹됩니다. 네트워크가 필요한 테스트는 깨진 테스트입니다.
* 🔍 **A7 점검** — 65개 전체 도구가 네 가지 중첩 깊이에서 비밀 값을 반환하는 업스트림을 대상으로 호출됩니다. 네거티브 컨트롤로 픽스처에 실제로 그 값이 포함되어 있음을 확인하므로 점검이 공허하게 통과될 수 없습니다.
* 📐 **스키마 드리프트 가드** — 작업 수, 페이로드 형태, 패키징된 데이터 파일이 모두 검증됩니다. 업스트림 업그레이드가 프로덕션에서 문제를 일으키기 전에 이 단계에서 실패하게 됩니다.

***

## 설계 메모

| 문서                                                                   | 내용                                                                   |
| :------------------------------------------------------------------- | :------------------------------------------------------------------- |
| [spec.md](spec.md)                                                   | 제품 계약 — 결정 **D1–D13**, 제어 **S1–S8**, 승인 기준 **A1–A10**                |
| Docs/api-surface.md에서 `[docs/api-surface.md](docs/api-surface.md)`   | 본문 필드와 필수 여부를 포함한 68개 전체 작업                                          |
| [docs/module-contract.md](docs/module-contract.md)                   | 내부 모듈 인터페이스                                                          |
| [docs/findings.md](docs/findings.md)                                 | 라이브 인스턴스를 기준으로 측정한, OpenAPI 문서에서 잘못된 두 가지                            |
| [`npm_mcp/data/npm-openapi.json`](src/npm_mcp/data/npm-openapi.json) | 인스턴스의 `/api/schema`를 그대로 복사한 것 — **패키지 안에 있음**. 문서가 아니라 런타임 의존성이기 때문 |

<div align="center">
<sub>Nginx Proxy Manager 2.15.1 기준으로 작성됨 · 44개 경로 · 68개 작업</sub>
</div>
A
license - permissive license
Not graded
quality - not tested
C
maintenance

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

  • A
    license
    B
    quality
    C
    maintenance
    Enables 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.
    50
    3
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to manage Nginx Proxy Manager instances through natural language, covering 28 tools for proxy hosts, certificates, streams, and more.
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables natural language management of FastPanel 2 servers, including creating sites, databases, SSL certificates, and hardening nginx configurations.
    32
    2
    MIT

View all related MCP servers

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.

View all MCP Connectors

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/omichelbraga/nginx-proxy-manager-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server