Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Arr Stack

БесплатноНе проверен

A Model Context Protocol server that exposes Sonarr, Radarr, Lidarr, and Jellyfin to any MCP client through a curated tool layer for LLM consumption.

GitHubEmbed

Описание

A Model Context Protocol server that exposes Sonarr, Radarr, Lidarr, and Jellyfin to any MCP client through a curated tool layer for LLM consumption.

README

A Model Context Protocol server that exposes Sonarr, Radarr, Lidarr, and Jellyfin to any MCP client (Claude Desktop, Claude Code, n8n, ibis-bot, custom agents) through a hand-curated tool layer written for LLM consumption.

License: MIT Python 3.12+

What this gives an agent

28 curated tools split across four services:

Service Tools Highlights
Sonarr 8 series search, TVDB lookup, queue, calendar, missing episodes, add/delete
Radarr 8 movie search, TMDB lookup, queue, calendar, missing, add/delete
Lidarr 7 artist + album search, MusicBrainz lookup, queue, add/delete
Jellyfin 5 library search, recent additions, now-playing sessions, library scan

Every tool:

  • Has a description written for an agent's decision-making, not for human docs.
  • Pins its input and output with Pydantic v2, so the MCP catalogue carries strict JSON Schema.
  • Returns a compact, self-describing envelope (ok, query, count, total, items).
  • Translates upstream HTTP errors into structured ToolError envelopes with self-suggesting hints.
  • Destructive operations require a two-call confirm-token flow.

Quickstart

uvx (one-shot)

uvx arr-stack-mcp serve --transport stdio

Docker

docker run --rm -i \
  -e SONARR_URL=http://host.docker.internal:8989 \
  -e SONARR_API_KEY=$SONARR_API_KEY \
  -e RADARR_URL=http://host.docker.internal:7878 \
  -e RADARR_API_KEY=$RADARR_API_KEY \
  -e LIDARR_URL=http://host.docker.internal:8686 \
  -e LIDARR_API_KEY=$LIDARR_API_KEY \
  -e JELLYFIN_URL=http://host.docker.internal:8096 \
  -e JELLYFIN_API_KEY=$JELLYFIN_API_KEY \
  ghcr.io/new-usemame/arr-stack-mcp:0.1.0

Local development (uv)

git clone https://github.com/new-usemame/arr-stack-mcp
cd arr-stack-mcp
uv sync
uv run arr-stack-mcp init           # writes a starter arr-stack-mcp.yaml
uv run arr-stack-mcp serve          # boots stdio MCP server

Claude Desktop config

Add to ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, or %APPDATA%\Claude\claude_desktop_config.json on Windows:

{
  "mcpServers": {
    "arr-stack": {
      "command": "uvx",
      "args": ["arr-stack-mcp", "serve"],
      "env": {
        "SONARR_URL": "http://localhost:8989",
        "SONARR_API_KEY": "...",
        "RADARR_URL": "http://localhost:7878",
        "RADARR_API_KEY": "...",
        "LIDARR_URL": "http://localhost:8686",
        "LIDARR_API_KEY": "...",
        "JELLYFIN_URL": "http://localhost:8096",
        "JELLYFIN_API_KEY": "..."
      }
    }
  }
}

Config reference

arr-stack-mcp init writes a starter arr-stack-mcp.yaml. Every secret can also be supplied via env var. Inline expansion of ${VAR} and ${VAR:-default} is supported.

log_level: info

transport:
  stdio: true
  http_enabled: false
  http_host: 127.0.0.1
  http_port: 8080

policy:
  read_only: false
  disable_destructive: false
  confirm_token_ttl_seconds: 300

services:
  sonarr:
    enabled: true
    url: http://localhost:8989
    api_key: ${SONARR_API_KEY}
    verify_tls: true
    timeout_seconds: 30
  radarr:
    enabled: true
    url: http://localhost:7878
    api_key: ${RADARR_API_KEY}
  lidarr:
    enabled: true
    url: http://localhost:8686
    api_key: ${LIDARR_API_KEY}
  jellyfin:
    enabled: true
    url: http://localhost:8096
    api_key: ${JELLYFIN_API_KEY}
    default_user_id: 4f8b6d2e-3a9c-4f1d-9c2a-1b3c5d7e9f01

Runtime flags

Flag Env Effect
--read-only ARRSTACK_READ_ONLY=true Skip every tool tagged write or destructive at registration.
--disable-destructive ARRSTACK_DISABLE_DESTRUCTIVE=true Skip only the destructive tools (deletes).
--dry-run Plan-and-record mode (v0.2). Write/destructive tools short-circuit before the upstream mutation and log the intended payload to a ring buffer surfaced by stack.dryrun_log. Reads run normally.
--transport stdio Default. Use for Claude Desktop and Claude Code.
--transport streamable-http HTTP transport for n8n / remote consumers.
--bearer-token-env ARR_STACK_MCP_BEARER_TOKEN (env name) Env var the server reads the bearer token from. Streamable-HTTP on a non-loopback bind refuses to start when this env var is unset.
--config path/to/config.yaml Override config path. Defaults to ./arr-stack-mcp.yaml, then XDG.

Confirm-token persistence (v0.2)

Confirm tokens default to in-memory storage. Set policy.state_db_path in the config to persist tokens across server restarts and across streamable-HTTP request lifetimes:

policy:
  state_db_path: ~/.local/state/arr-stack-mcp/state.db

The path is created idempotently. SQLite WAL mode lets multiple worker processes share the same DB safely.

Hourly per-tool call cap (v0.2)

Opt-in runaway-agent protection. Tools without an entry are uncapped:

policy:
  hourly_caps:
    sonarr.series_add: 50
    radarr.movie_add: 50
    sonarr.series_delete: 10

Per-process, per-tool, rolling-hour. Failed upstream calls still consume budget so a runaway loop hits the cap on the Nth attempt.

Capability matrix

Tools follow the <service>.<verb_object> convention. Tags drive flag-based gating.

Sonarr

Tool Tag Use
sonarr.system_status read Version + branch + uptime. First call when diagnosing.
sonarr.series_search read Search the existing library (already-added).
sonarr.series_lookup read Search TVDB to discover series to add.
sonarr.series_status read Per-season breakdown (v0.2). Episode counts, files on disk, missing.
sonarr.queue read Active downloads with progress.
sonarr.calendar read Upcoming + recently-aired episodes.
sonarr.missing read Monitored episodes not on disk.
sonarr.series_add write Add a series by TVDB id. Idempotent.
sonarr.series_delete destructive Two-call confirm-token flow.

Radarr

Tool Tag Use
radarr.system_status read Mirrors Sonarr.
radarr.movie_search read Search the existing library.
radarr.movie_lookup read Search TMDB to discover movies to add.
radarr.queue read Active downloads.
radarr.calendar read Upcoming + recently-released movies.
radarr.missing read Monitored movies not on disk.
radarr.movie_add write Add a movie by TMDB id. Idempotent.
radarr.movie_delete destructive Two-call confirm-token flow.

Lidarr

Tool Tag Use
lidarr.system_status read
lidarr.artist_search read Search the existing library.
lidarr.artist_lookup read Search MusicBrainz to discover artists.
lidarr.artist_albums read List albums under one artist.
lidarr.queue read Active downloads.
lidarr.artist_add write Add an artist by MusicBrainz id. Idempotent.
lidarr.artist_delete destructive Two-call confirm-token flow.

Jellyfin

Tool Tag Use
jellyfin.system_info read Version + server name. Public endpoint.
jellyfin.library_search read Search items by name. Pass user_id= for per-user scoping (v0.2).
jellyfin.recent_additions read Newest items by date_added. Pass user_id= for per-user scoping (v0.2).
jellyfin.users_list read Enumerate user accounts (v0.2). Returns user_id, name, admin flag, last login.
jellyfin.now_playing read Currently-active sessions with progress.
jellyfin.scan_library write Trigger a library refresh.

Prowlarr (v0.2)

Tool Tag Use
prowlarr.system_status read Version + branch. First call when diagnosing Prowlarr.
prowlarr.health read Health-check issues (warnings, errors, wiki links).
prowlarr.indexer_list read Configured indexers with implementation, protocol, priority, enable.
prowlarr.indexer_stats read Query / grab / failure counts per indexer + average response time.
prowlarr.indexer_status read Currently-failing indexers with retry-after timestamps.
prowlarr.indexer_test_all write Trigger the test-every-indexer probe; returns per-indexer pass/fail.
prowlarr.search read Search across configured indexers. Returns title, indexer, size, age, seeders. Does NOT download — use *.add on Sonarr / Radarr / Lidarr with catalog id.

stack.* (v0.2, cross-service)

Tool Tag Use
stack.health read Probe every enabled service's *.system_status in parallel. Returns reachability matrix + overall_ok.
stack.dryrun_log read Read the ring buffer of would-have-fired mutations recorded under --dry-run.
stack.report_issue read Compose a pre-filled GitHub issue URL the user can post upstream. Never auto-submits.
stack.find_anywhere read Fan a query across every enabled arr + Jellyfin library; merged result with source per row.
stack.queue_status_all read Aggregate download queue across Sonarr, Radarr, Lidarr. Normalized row shape.

Confirm-token flow

Destructive tools (*_delete) implement a two-call confirm:

# Call 1: returns plan + token, no side effect
> sonarr.series_delete(sonarr_id=42, delete_files=False)
{
  "ok": true,
  "needs_confirm": true,
  "confirm_token": "abc123",
  "summary": "remove 'Foo Bar' (sonarr_id=42) from Sonarr; keep files on disk",
  "expires_in_seconds": 300
}

# Call 2: executes
> sonarr.series_delete(sonarr_id=42, delete_files=False, confirm_token="abc123")
{
  "ok": true,
  "deleted_sonarr_id": 42,
  "title": "Foo Bar",
  "files_deleted": false,
  "msg": "deleted sonarr_id=42"
}

Tokens are single-use, time-limited, and bound to the request payload — a token from one tool will not confirm another.

Architecture

Two layers:

┌────────────────────────────────────────────────────────────┐
│  Curated MCP tools (arr_stack_mcp.tools.<service>.tools)  │
│  Hand-written, LLM-friendly names, descriptions, schemas. │
├────────────────────────────────────────────────────────────┤
│  Generated thin clients (arr_stack_mcp.generated.<svc>)   │
│  openapi-python-client output. Do not hand-edit; regen    │
│  via scripts/regen-clients.sh on upstream version bumps.  │
├────────────────────────────────────────────────────────────┤
│  httpx + pydantic + structlog + mcp.server.fastmcp         │
└────────────────────────────────────────────────────────────┘

See docs/ARCHITECTURE.md for the longer walk-through.

Development

uv sync                              # install runtime + dev deps
uv run pytest -q                     # fast unit tests
uv run ruff check src/ tests/        # lint
uv run mypy src/ tests/              # type check (strict)
uv run ruff format src/ tests/       # format

Integration tests require the docker test stack:

scripts/test-stack-up.sh             # boots Sonarr/Radarr/Lidarr/Prowlarr/Jellyfin
uv run pytest -m integration         # runs once stack is healthy
scripts/test-stack-down.sh --clean   # teardown

Contributing

See CONTRIBUTING.md for the OpenAPI regeneration flow and the verification checklist that gates every release.

License

MIT

from github.com/new-usemame/arr-stack-mcp

Установить Arr Stack в Claude Desktop, Claude Code, Cursor

Рекомендуется · одна команда, все IDE
unyly install arr-stack-mcp

Ставит в Claude Desktop, Claude Code, Cursor и VS Code — сам разбирается с npx, uvx и сборкой из исходников.

Впервые? Поставь CLI: curl -fsSL https://unyly.org/install | sh

Или настроить вручную

Выполни в терминале:

claude mcp add arr-stack-mcp -- uvx arr-stack-mcp

FAQ

Arr Stack MCP бесплатный?

Да, Arr Stack MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Arr Stack?

Нет, Arr Stack работает без API-ключей и переменных окружения.

Arr Stack — hosted или self-hosted?

Доступен hosted-вариант: Unyly запускает сервер в облаке, локальная установка не обязательна.

Как установить Arr Stack в Claude Desktop, Claude Code или Cursor?

Открой Arr Stack на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Arr Stack with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории ai