Skip to main content
Glama
CarlDog
by CarlDog

plex-mcp

code confidence · claude-opus-4-8[1m] · 2026-07-07 · 세부 정보

Plex Media Server용 MCP 서버로, Docker 컨테이너로 패키징되어 있습니다. MCP 클라이언트(Claude Desktop 등)가 Plex 라이브러리를 탐색하고 검색할 수 있게 해줍니다.

도구

도구

설명

plex_list_libraries

서버의 모든 라이브러리(섹션)를 나열합니다.

plex_search

모든 라이브러리에서 검색합니다.

plex_hub_search

Plex의 허브 검색 엔드포인트로 검색하며 컬렉션도 포함합니다(plex_search와 달리).

plex_recently_added

최근 추가된 항목(선택적으로 섹션별).

plex_on_deck

"on deck" 항목(부분 시청/다음에 볼 항목). 선택적 section_id로 하나의 라이브러리 섹션으로 범위를 제한합니다.

plex_get_item

rating key로 단일 항목의 메타데이터를 가져옵니다. minimal=true를 전달하면 방대한 출연진/스태프/이미지 배열을 제거하고(출연진이 많은 영화의 경우 약 80% 크기 감소) 자막 트랙 정보는 유지합니다. 명시적 프로젝션을 위해 fields=[...]를 전달합니다.

plex_browse

라이브러리 섹션의 항목을 나열합니다(페이지 단위, 선택적 유형 필터, 선택적 collection 제목 필터, 선택적 희소 fields 프로젝션).

plex_list_collections

라이브러리 섹션의 컬렉션을 나열합니다(plex_browse의 컬렉션 유형에 대한 얇은 래퍼).

plex_get_children

항목의 하위 항목(시리즈→시즌, 시즌→에피소드, 아티스트→앨범).

plex_now_playing

서버에서 현재 재생 중인 세션.

plex_history

재생 기록 항목(페이지 단위, 최신순).

plex_mark_watched

항목을 시청함으로 표시합니다(되돌리기 가능).

plex_mark_unwatched

항목을 시청 안 함으로 표시합니다(되돌리기 가능).

plex_rate_item

항목의 사용자 별점(0-10)을 설정합니다. rating을 생략하면 미평가 상태로 되돌립니다.

plex_list_playlists

모든 재생 목록을 나열합니다(일반 + 스마트).

plex_get_playlist_items

재생 목록의 내용을 나열합니다.

plex_create_playlist

하나의 항목으로 시작하는 일반 재생 목록을 생성합니다.

plex_add_to_playlist

일반 재생 목록에 항목을 추가합니다.

plex_remove_from_playlist

playlistItemID로 항목을 제거합니다.

plex_delete_playlist

재생 목록을 삭제합니다(메타데이터만 — 미디어는 변경되지 않음).

plex_hubs

Plex의 큐레이팅된 서버 전체 허브(계속 시청, 최근 공개 등).

plex_section_hubs

하나의 라이브러리 섹션으로 범위가 한정된 큐레이팅된 허브.

plex_related

항목에 대한 Plex의 큐레이팅된 "관련" 허브(출처별 그룹화).

plex_similar

항목에 대한 알고리즘 기반 유사 항목(단순 목록).

plex_refresh_metadata

현재 에이전트에서 항목의 메타데이터를 다시 가져옵니다(선택적 force).

plex_get_matches

항목에 대한 후보 일치 항목을 나열합니다(TMDB / TVDB 등). 선택적 제목/연도/에이전트/언어 재정의.

plex_apply_match

선택한 일치 항목(guid/name)을 항목에 적용합니다. 에이전트 바인딩을 덮어씁니다.

plex_edit_metadata

필드 수준 잠금으로 스칼라 메타데이터 필드(제목, 요약, 연도 등)를 재정의합니다.

plex_unmatch

항목을 에이전트 바인딩에서 분리합니다(미매칭 상태로 복귀). 잠긴 필드는 유지됩니다.

plex_refresh_section

전체 라이브러리 섹션의 메타데이터 새로고침을 트리거합니다(증분 또는 전체).

plex_split_item

Plex 항목을 구성 미디어 변형들로 분할하여 N개의 개별 항목으로 되돌립니다.

plex_merge_items

다른 항목들을 대상 항목으로 병합합니다(소스는 흡수되고 대상은 유지됨).

plex_get_image

항목의 포스터/아트/배너/clearLogo 바이트를 MCP 이미지 콘텐츠 블록으로 가져옵니다(비전 지원 클라이언트가 실제로 이미지를 볼 수 있도록). 선택적 max_width/max_height는 Plex의 트랜스코더를 통해 처리됩니다.

plex_save_image

plex_get_image와 동일한 입력 인터페이스를 가지지만, 바이트를 MCP_IMAGE_SAVE_DIR(기본값 /data/images/) 아래 디스크에 기록하고 경로와 크기를 반환합니다. 비전 렌더링 없이 호스트 디렉터리를 해당 경로에 바인드 마운트하여 다운스트림 파이프라인(ImageMagick, filesystem-mcp 소비자 등)으로 연결할 수 있습니다.

plex_download_logs

Plex Media Server 자체 진단 로그 번들(ZIP)을 가져와 MCP_LOG_SAVE_DIR(기본값 /data/logs/) 아래 디스크에 기록합니다.

plex_list_posters

항목의 모든 포스터 후보(에이전트 제공, 로컬 스캔, 이전 업로드)를 나열하며, 현재 활성화된 포스터도 함께 표시합니다.

plex_set_poster

plex_list_posters에서 해당 후보의 poster_rating_key를 사용하여 기존 포스터 후보를 활성 포스터로 선택합니다.

plex_upload_poster

외부 URL(Plex가 가져옴) 또는 MCP_IMAGE_SAVE_DIR 아래의 로컬 파일에서 새 포스터를 추가합니다. 기본적으로 자동 선택되며, select=false를 전달하면 표시 중인 포스터를 변경하지 않고 추가만 합니다.

Related MCP server: Plex Assistant MCP

구성

두 개의 환경 변수가 있으며, 둘 다 필수입니다:

변수

예시

참고 사항

PLEX_URL

http://192.168.1.50:32400

Plex 서버의 기본 URL

PLEX_TOKEN

(아래 참조)

Plex 인증 토큰

Plex 토큰을 찾으려면 Plex의 인증 토큰 찾기 가이드를 참조하세요.

선택적 환경 변수

모두 사용 가능한 기본값이 있으며, 재정의할 경우에만 설정하세요.

변수

기본값

참고 사항

MCP_FETCH_TIMEOUT_MS

30000

로그 다운로드를 제외한 모든 아웃바운드 Plex 요청의 타임아웃

MCP_IMAGE_MAX_BYTES

4194304 (4 MiB)

plex_get_image/plex_save_image 의 크기 상한

MCP_LOG_MAX_BYTES

52428800 (50 MiB)

plex_download_logs 의 크기 상한

MCP_LOG_FETCH_TIMEOUT_MS

120000 (2분)

plex_download_logs 의 타임아웃 — 로그 ZIP은 크기/지연 프로파일이 다르므로 MCP_FETCH_TIMEOUT_MS 와 분리되어 있습니다.

MCP_SESSION_IDLE_TIMEOUT_MS

3600000 (1시간)

이 기간 동안 비활성 상태인 HTTP 모드 MCP 세션을 축출합니다.

LOG_LEVEL, MCP_ALLOWED_HOSTS/MCP_ALLOWED_ORIGINS, HOST_IMAGE_DIR/HOST_LOG_DIR 는 각각 한 줄 설명으로는 부족하므로 아래의 각 섹션(로깅, HTTP 전송 보안 강화, Portainer 배포)에서 다룹니다.

Plex가 컨테이너와 같은 호스트에 있나요? PLEX_URL=http://host.docker.internal:32400 을 사용하세요. compose 파일은 extra_hosts 를 통해 host.docker.internal 을 Docker 호스트 게이트웨이에 매핑하므로 컨테이너가 호스트에서 실행 중인 Plex 서버에 도달할 수 있습니다. 해당 매핑 없이는 호스트 자체의 호스트 이름(예: my-nas)이 컨테이너 내부에서 확인되지 않습니다.

전송 모드

모드

사용 시점

시작 방법

stdio (기본값)

Claude Desktop / MCP 클라이언트가 직접 호출

docker run -i --rm ... plex-mcp (MCP_PORT 없음)

Streamable HTTP

장기 실행 배포 (Portainer, Compose, k8s)

MCP_PORT=3000 설정 (이미 docker-compose.yml에 되어 있음)

HTTP 모드에서 서버는 다음을 노출합니다:

  • POST/GET/DELETE /mcp — MCP Streamable HTTP 엔드포인트 (사양에 따름)

  • GET /health — 활성 프로브 (docker healthcheck에서 사용)

HTTP 모드에는 호출자 인증이 없습니다 — TLS(아래)는 트래픽을 암호화하지만 호출자를 식별하지는 않습니다. 반드시 사설 네트워크에만 바인딩하세요. 호스트 방화벽이나 LAN 격리에 의존하세요. 먼저 bearer-token 인증을 추가하지 않고 공개 인터넷에 노출하지 마세요.

HTTPS 활성화

HTTPS는 선택 사항입니다. 시작 시 확인 순서:

  1. 자체 인증서 가져오기 — MCP_TLS_CERT_FILE 과 MCP_TLS_KEY_FILE 를 모두 PEM 파일 경로로 설정하세요. Let's Encrypt 또는 내부 CA 인증서를 사용해 TLS를 종료하는 경우에 이 방법을 사용하세요. 서버는 시작 시 이 파일들을 읽습니다. 갱신된 파일을 적용하려면 컨테이너를 다시 시작하세요.

  2. 자체 관리 인증서 (LAN 전용 설정에 권장) — MCP_TLS=auto 로 설정하세요. 서버는 첫 시작 시 ECDSA P-256 자체 서명 인증서를 생성하여 MCP_TLS_DIR (기본값 /data/certs)에 쓰고 이후 시작에서 이를 재사용합니다. 인증서의 만료가 30일 이내로 남으면 자동으로 재생성됩니다.

  3. 그 외에는 서버가 일반 HTTP로 유지됩니다 (현재 기본값).

변수

기본값

참고 사항

MCP_TLS

설정 안 됨

auto / true / on / 1 로 자체 관리 모드 활성화

MCP_TLS_DIR

/data/certs

server.crt / server.key 가 있는 위치. 지속성을 위해 볼륨을 마운트하세요.

MCP_TLS_SAN

DNS:localhost,IP:127.0.0.1

Subject Alternative Names. 쉼표로 구분된 DNS: / IP: 항목.

MCP_TLS_CN

첫 번째 DNS SAN, 없으면 plex-mcp

인증서 공통 이름.

MCP_TLS_DAYS

365

유효 기간. 남은 기간이 30일 미만이면 인증서가 교체됩니다.

MCP_TLS_CERT_FILE

설정 안 됨

자체 인증서 (PEM). 키와 함께 설정하면 MCP_TLS=auto 를 재정의합니다.

MCP_TLS_KEY_FILE

설정 안 됨

자체 키 (PEM).

시작 시 서버는 인증서의 SHA-256 지문과 notAfter 를 기록합니다. 클라이언트 측에서 지문을 고정(pin)하거나 브라우저 및 CLI 도구를 위해 OS 키 저장소에서 인증서를 신뢰하세요.

TLS가 켜져 있으면 compose healthcheck에 --no-check-certificate 플래그가 필요합니다 — test: 줄을 ["CMD", "wget", "--no-check-certificate", "-q", "-O-", "https://localhost:3000/health"] 로 업데이트하세요.

HTTPS 엔드포인트를 가리키도록 mcp-remote 설정

자체 서명 인증서의 경우 Node의 CA 번들을 통해 인증서 파일을 고정하거나 클라이언트에서 검증을 건너뛰세요 (LAN 전용):

# Trust the server's self-signed cert (preferred):
NODE_EXTRA_CA_CERTS=./server.crt \
  npx -y mcp-remote https://nas.local:3443/mcp

# Or skip verification for quick testing (LAN-only):
NODE_TLS_REJECT_UNAUTHORIZED=0 \
  npx -y mcp-remote https://nas.local:3443/mcp

리버스 프록시 대안

프로세스 내 TLS는 이미 인그레스 컨트롤러를 실행하지 않는 경우 편리합니다. 홈 서비스 앞에 Caddy, Traefik 또는 nginx가 있다면 더 일반적인 패턴은 프록시에서 TLS를 종료(자동 Let's Encrypt 포함)하고 그 뒤에서 plex-mcp 를 일반 HTTP로 유지하는 것입니다. 두 방식은 서로 바꿔 사용할 수 있습니다 — 기존 설정에 맞는 쪽을 선택하세요.

OAuth 2.1 bearer-token 인증 (선택 사항, 아직 실질적으로 사용 불가)

OAuth 2.1 보호 리소스 인증에 대한 코드 측 지원은 존재합니다 (ChatGPT Apps SDK 정렬 2단계 — 전체 계획은 docs/CHATGPT-APPS-SDK.md 참조). 그러나 아직 실제로 켜서 사용할 수 있는 것은 아닙니다: 토큰을 발급하는 실제 OAuth 2.1 ID 공급자가 필요하며 이 배포에는 제공된 것이 없습니다 (그것은 아직 시작하지 않은 3단계입니다). 완전성을 위해 문서화된 것이지, 사용 방법 안내가 아닙니다.

변수

참고 사항

MCP_OAUTH_ISSUER

IdP 발급자 URL. 이 값을 설정하면 인증이 활성화됩니다 — 설정 안 됨(기본값)은 현재와 동일하게 인증 없음을 의미합니다.

MCP_OAUTH_AUDIENCE

MCP_OAUTH_ISSUER 가 설정되면 필수입니다. 기대되는 aud 클레임 — 이 서버의 정식 공개 URL과 같아야 합니다. 없으면 서버가 시작을 거부합니다.

MCP_OAUTH_REQUIRED_SCOPES

쉼표로 구분. 기본값 plex:read.

활성화되면 모든 /mcp 요청에는 올바른 audience와 scope를 가진, 구성된 IdP에서 발급된 Authorization: Bearer <jwt> 가 필요합니다. /health 는 영향을 받지 않습니다 (별도 경로이며, Docker 자체 healthcheck에는 bearer 토큰을 첨부할 방법이 없습니다). /.well-known/oauth-protected-resource 는 RFC 9728에 따라 자동으로 제공됩니다.

Docker로 실행 (stdio, 필요 시)

docker build -t plex-mcp .
docker run -i --rm \
  -e PLEX_URL=http://192.168.1.50:32400 \
  -e PLEX_TOKEN=your-token \
  plex-mcp

Docker Compose로 실행 (HTTP, 장기 실행)

compose 파일은 ghcr.io/carldog/plex-mcp:latest (멀티 아키텍처: linux/amd64 + linux/arm64)를 가져오며, CI가 main 에 푸시할 때마다 게시합니다.

# Required env vars (or use a .env file):
export PLEX_URL=http://192.168.1.50:32400
export PLEX_TOKEN=your-token
export MCP_ALLOWED_HOSTS=nas.local:3001  # required — see below
export HOST_PORT=3001  # optional, defaults to 3001

docker compose up

MCP 엔드포인트는 http://<host>:${HOST_PORT}/mcp 에 있습니다.

풀 대신 소스에서 다시 빌드하려면:

docker build -t ghcr.io/carldog/plex-mcp:latest .
docker compose up

Portainer로 배포 (Git 스택)

  1. Portainer에서 Stacks → Add Stack → Repository 로 이동합니다.

  2. Repository URL: https://github.com/CarlDog/plex-mcp

  3. Compose path: docker-compose.yml

  4. 환경 변수: PLEX_URL, PLEX_TOKEN, MCP_ALLOWED_HOSTS, HOST_IMAGE_DIR, HOST_LOG_DIR 설정 — 모두 필수 (아래 참조); 선택적으로 HOST_PORT.

  5. 배포합니다. Healthcheck는 ~10초 이내에 녹색이 됩니다.

MCP_ALLOWED_HOSTS 는 HTTP 모드에서 필수입니다

서버가 /mcp 에서 허용하는 Host 헤더 값의 쉼표로 구분된 목록 — 예: nas.local:3001 (클라이언트가 실제로 연결하는 host:port와 일치해야 하며 매핑된 HOST_PORT 포함). 이 값이 없으면 서버는 HTTP 모드에서 시작을 거부하고, docker compose config 도 설정되지 않은 경우 동일하게 실패합니다 — 둘 다 의도적으로 컨테이너가 뜨기 전에 실패하여 조용히 보호되지 않은 상태로 시작하지 않습니다.

이는 컨테이너 내부에서 0.0.0.0 에 바인딩하는 것이 일반 호스트에서의 루프백 바인딩과 같은 실제 접근 경계가 아니기 때문입니다: LAN의 어느 곳에서든 브라우저에 로드된 페이지가 DNS 리바인딩을 수행할 수 있습니다 — 자신의 호스트 이름을 이 컨테이너의 IP로 지정 — 그리고 혼동된 대리자(confused deputy)로서 도구( plex_delete_playlist 와 같은 쓰기 포함)를 구동하여 "LAN 전용, bearer 토큰 없음"이라는 보안 자세를 완전히 우회할 수 있습니다. Host 허용 목록은 전체 인증을 요구하지 않고 이 공백을 메웁니다. MCP_ALLOWED_ORIGINS (선택 사항, 기본값 비어 있음)는 Origin 헤더에 대해 동일한 역할을 합니다 — 브라우저 기반 클라이언트가 이 서버를 직접 호출해야 하는 정당한 필요가 없는 한 설정하지 마세요. 비브라우저 클라이언트( mcp-remote 브리지, 직접 fetch )는 Origin 헤더를 보내지 않으므로 빈 기본값은 DNS 리바인딩 공격이 실제로 보내는 요청 형태만 거부합니다.

HOST_IMAGE_DIR 및 HOST_LOG_DIR 필수 — 상대 경로 기본값 없음

두 볼륨 호스트 경로 모두 compose 파일에서 ${VAR:?...} 입니다: 대체 기본값이 없으므로 둘 중 하나라도 설정되지 않으면 docker compose up / Portainer 재배포가 중단된 상태로 시작하는 대신 명확한 오류와 함께 빠르게 실패합니다.

이전에는 ${VAR:-./data/images} 라는 관대한 기본값이 있었으며, 안정적인 클론에서 로컬로 docker compose up 을 실행할 때만 안전했습니다. Portainer git 스택에서는 함정입니다: 재배포할 때마다 저장소가 새 커밋별 디렉터리(/data/compose/<stack-id>/<commit>/)로 클론되며 ./data/images 같은 상대 경로는 그곳에 존재하지 않습니다. Docker는 바인드 마운트를 거부했고 컨테이너는 created 상태에 갇힌 채 시작되지 않았습니다. 이 문제는 자동 재배포(이미지 업데이트, git 폴링)에도 영향을 주어, 이전에 정상이던 스택이 수동 조작 없이 다운되었습니다. 유일한 증상은 컨테이너가 created 상태에 머물러 있는 것이었습니다. 이로 인해 배포된 스택이 2026-07-31에 ~10시간 동안 다운되었습니다 — docker-deployments.md 규칙 #10 및 교훈 2026-07-31-relative-compose-volume-defaults-break-portainer-git-stacks 참조. compose 파일은 이제 이 요구 사항을 문서화 전용 규칙이 아니라 구조적으로 규정합니다.

스택의 환경 변수에서 둘 다 절대 호스트 경로로 설정하세요:

  • HOST_IMAGE_DIR — plex_save_image 출력 디렉터리입니다. 권장: filesystem-mcp의 /media/_mcp-scratch 마운트에 해당하는 호스트 디렉터리 — 예: Synology NAS의 /volume1/Media/_mcp-scratch — 즉 plex_search → plex_save_image → filesystem-mcp 파이프라인이 하나의 공유 디렉터리에서 유지됩니다.

  • HOST_LOG_DIR — plex_download_logs 출력 디렉터리이며, 진단 ZIP은 미디어 산출물이 아니므로 HOST_IMAGE_DIR과 분리되어 있습니다 — 예: Synology NAS의 /volume1/docker/plex-mcp/logs (이 플릿의 컨테이너별 appdata 규칙에 따름).

첫 배포 전에 두 디렉터리가 호스트에 존재하는지 확인하세요: Docker는 누락된 바인드 마운트 소스를 자동 생성하지 않으며, 컨테이너 시작을 거부할 뿐입니다.

Claude Desktop에서 사용

stdio (로컬 실행)

{
  "mcpServers": {
    "plex": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "PLEX_URL", "-e", "PLEX_TOKEN",
        "plex-mcp"
      ],
      "env": {
        "PLEX_URL": "http://192.168.1.50:32400",
        "PLEX_TOKEN": "your-token"
      }
    }
  }
}

HTTP (원격 MCP 서버)

{
  "mcpServers": {
    "plex": {
      "url": "http://nas.local:3001/mcp"
    }
  }
}

(Claude Desktop 또는 원격 MCP HTTP를 지원하는 클라이언트가 필요합니다.)

로컬 개발

npm install
cp .env.example .env  # then edit
PLEX_URL=... PLEX_TOKEN=... npm run dev               # stdio
MCP_PORT=3000 MCP_ALLOWED_HOSTS=localhost:3000 PLEX_URL=... PLEX_TOKEN=... npm run dev # HTTP

로깅

서버는 구조화된 로그를 stderr로 출력합니다(stdout은 stdio 모드에서 MCP 와이어 프로토콜이므로 오염되어서는 안 됩니다). 형식:

2026-04-29T15:30:00.000Z INFO [tool:plex_browse] invoke section_id=7 type=show limit=2
2026-04-29T15:30:00.337Z INFO [tool:plex_browse] ok ms=337

상세 수준은 LOG_LEVEL 환경 변수로 구성합니다(기본값 info):

레벨

표시

error

오류만

warn

+ 4xx Plex 응답

info (기본값)

+ 도구 호출 및 완료

debug

+ 메서드, 경로, 상태, ms를 포함한 모든 Plex API 호출

trace

(예약됨)

컨테이너 로그는 Docker의 json-file 드라이버로 수집되며 자동으로 순환됩니다(10MB × 3개 파일 = ~30MB 상한; 순환 시 가장 오래된 파일 삭제). docker logs plex-mcp 또는 docker logs -f로 확인하세요.

보안

  • 컨테이너는 비-root 사용자(plexmcp)로 실행됩니다.

  • Plex 토큰은 환경 변수로 전달됩니다 — 이미지에 절대 포함하지 마세요.

  • .githooks/pre-commit은 모든 커밋에서 gitleaks를 실행합니다. 클론마다 한 번 활성화하세요: git config core.hooksPath .githooks

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables users to manage and control their Plex media library through natural language commands in MCP-compatible AI clients. It supports searching content, managing playlists, tracking library statistics, and monitoring live viewing sessions.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for reelgrep - browse and search your local video library from any MCP client.
    10 npm
    MIT