{
  "markdown": "<div align=\"center\">\n\n<img src=\"assets/logo.svg\" alt=\"\" width=\"64\" height=\"64\">\n\n# arr-mcp\n\n### Talk to your entire media stack. One server, one endpoint, one conversation.\n\n**Radarr · Sonarr · Prowlarr · Bazarr · Jellyfin · Plex · Seerr · SABnzbd · Transmission · qBittorrent**\n\n[![Release](https://img.shields.io/github/v/release/bardesss/arr-mcp?style=flat-square&color=6f42c1)](https://github.com/bardesss/arr-mcp/releases)\n[![CI](https://img.shields.io/github/actions/workflow/status/bardesss/arr-mcp/ci.yml?branch=main&style=flat-square)](https://github.com/bardesss/arr-mcp/actions)\n[![Image](https://img.shields.io/badge/ghcr.io-arr--mcp-2496ed?style=flat-square&logo=docker&logoColor=white)](https://github.com/bardesss/arr-mcp/pkgs/container/arr-mcp)\n[![Platforms](https://img.shields.io/badge/platforms-amd64%20%C2%B7%20arm64-555?style=flat-square)](https://github.com/bardesss/arr-mcp/pkgs/container/arr-mcp)\n[![Licence](https://img.shields.io/badge/licence-MIT-green?style=flat-square)](LICENSE)\n\n<img src=\"screenshots/dashboard-dark.png\" alt=\"The arr-mcp dashboard: every configured service tested live, with status, latency and version\" width=\"880\">\n\n</div>\n\n## Everyone else ships one MCP server per service. This is one for the stack.\n\nThat difference is the whole point, because the interesting questions live\n*between* services:\n\n> *\"Why isn't the film I requested on Tuesday showing up in Jellyfin?\"*\n\nNo single service can answer that. It spans Seerr, Radarr, Prowlarr, SABnzbd and\nJellyfin — five APIs, five sets of ids, five half-answers. arr-mcp correlates\nthem and hands back the causal chain:\n\n```\ndiagnose { query: \"Blade\" }\n```\n\n> No file on disk yet. Trigger a search in Radarr or Sonarr — nothing is\n> downloading and no indexer reported a failure.\n\nOne call. One answer. It even answers with a service down, and tells you which\npart it could not check rather than guessing across the hole.\n\n## Why people run it\n\n|  | |\n| --- | --- |\n| 🔍 **`diagnose` answers what no single service can** | Walks the whole chain — requested, managed, monitored, downloaded, indexed, imported, scanned — and names the *first* thing that explains the absence. |\n| 🛡️ **Indexer text is data, never instruction** | Release names from public indexers are attacker-controllable and flow straight into model context. arr-mcp fences every one of them. |\n| ✋ **Writes are opt-in, previewed, recorded** | Off until you turn them on, per service. Every write shows you exactly what it would do and waits for confirmation — and lands in an audit trail either way. |\n| 🖥️ **A config page that diagnoses** | Add services from a browser, see what is broken *and what to do about it*, read the logs and the write audit. No YAML required. |\n| 📚 **Thirty-four tools, one vocabulary** | Every list pages the same way, every error names the config key that would fix it, every write takes ids rather than titles. |\n\nNothing else in this space does the last four at all.\n\n## Quick start — about two minutes\n\nAlso in the repo as [`docker-compose.example.yml`](docker-compose.example.yml).\n**On Unraid**, use [`unraid/arr-mcp.xml`](unraid/arr-mcp.xml) instead — a\nCommunity Applications template with the appdata path and `99:100` ownership\nalready set. It is not listed in CA yet, so for now drop it into\n`/boot/config/plugins/dockerMan/templates-user/` and pick it from the template\nlist under **Add Container**. Steps 1 to 3 below are the same once it starts.\n\n```yaml\nservices:\n  arr-mcp:\n    image: ghcr.io/bardesss/arr-mcp:latest\n    container_name: arr-mcp\n    ports:\n      - 6060:6060\n    volumes:\n      - ./config:/config\n    environment:\n      - PUID=1000\n      - PGID=1000\n      - TZ=Europe/Amsterdam\n    restart: unless-stopped\n```\n\n**1. Open `http://<host>:6060`** — the bare host, no path. Nothing to read out\nof the container log.\n\n**2. Claim it.** The first page is a setup form rather than a sign-in: choose a\nusername and a password of at least 12 characters.\n\n> [!IMPORTANT]\n> Do this **before** exposing the port. Until it is claimed, whoever loads that\n> page first owns the instance — and it holds every service's API key.\n\n**3. Add your services** — **Add a service**, paste its URL and API key (or, for\nTransmission and qBittorrent, its username and password), save. It applies immediately; there is\nno restart. Configure only what you run. A config file that will not parse no\nlonger takes the container down: arr-mcp serves a repair page with the error and\nan editor instead.\n\nYour MCP client goes to `http://<host>:6060/mcp` with the bearer token shown on\nthe dashboard. A client that can only be given a URL, not a header, can carry\nthe token as `?token=` instead — see\n[`allow_token_in_url`](docs/configuration.md#allow_token_in_url). Everything\nthe UI does is still just `config.yaml`, and editing that by hand remains\nsupported. Clients that read the\n[MCP Registry](https://registry.modelcontextprotocol.io) find it there as\n`io.github.bardesss/arr-mcp`.\n\n**Works with whatever you point at it.** A client asking for\n`Accept: application/json` — or sending no `Accept` at all — gets one JSON object\nback with a `Content-Length`, rather than a refusal for not also naming\n`text/event-stream`. A client that does accept a stream still gets one. Even a\nrefusal is JSON. So a plain `curl` works as-is, and so does a full MCP client.\n\nImage tags are `X.Y.Z`, `X.Y`, `X` and `latest`, plus `main` for bleeding edge.\nPin a minor — `:1.6` — if you would rather approve each new tool surface\nyourself. Images are published for **amd64 and arm64**, so a Raspberry Pi or an\nARM NAS runs the same build as everything else.\n\n## What you can ask it\n\nThirty-four tools, but you never name them — you ask, and the model picks:\n\n> *\"What's downloading right now, and is anything stuck?\"*\n> *\"What aired this week that I haven't watched?\"*\n> *\"Which of my indexers are failing, and what did they say?\"*\n> *\"Find me something highly rated from 1994 I don't already have.\"*\n> *\"Go and find Dutch subtitles for the film that just landed.\"*\n> *\"Not that release — grab the 1080p remux instead.\"*\n> *\"Why does this episode keep failing and never downloading?\"*\n> *\"Pause SABnzbd, I need the bandwidth for an hour.\"*\n> *\"That download finished days ago and never got imported — sort it out.\"*\n> *\"Put this series on the 4K profile and only monitor future seasons.\"*\n> *\"Unmonitor season 5 and delete its files.\"* — previewed first, always.\n\n## Documentation\n\n| | |\n| --- | --- |\n| **[Tools](docs/tools.md)** | All thirty-four, what each answers, and the fields whose meaning is not obvious |\n| **[Writes](docs/writes.md)** | Turning them on, the two tiers, and the preview-and-confirm handshake |\n| **[Configuration](docs/configuration.md)** | `config.yaml`, several Radarrs, Jellyfin's `default_user` |\n| **[Config UI](docs/config-ui.md)** | The four pages, and what each does that is not obvious |\n| **[IMDb ratings](docs/imdb.md)** | The only way to get an IMDb score for a series, and what it costs |\n| **[Security](docs/security.md)** | The threat model, walked against the OWASP MCP Top 10, including what it does not solve |\n| **[Contributing](CONTRIBUTING.md)** | [Which services qualify](CONTRIBUTING.md#which-services-qualify), how to add an adapter, and the rules an AI agent tends to break |\n\n## Requirements\n\n- At least one supported service, LAN-reachable: Radarr 4.0+, Sonarr 4.0+,\n  Prowlarr 1.0+, Bazarr 1.4+, Jellyfin 10.8+, Seerr 1.0+, SABnzbd 3.0+,\n  Transmission 3.0+, qBittorrent 4.1+\n- Docker, or Node 24+ to run from source\n- An MCP client speaking protocol revision `2026-07-28`\n\nSince 1.0 the tool surface is the public API: renaming or removing a tool, a\nparameter or a response field is a **major**, because that break is silent — a\nmodel stops finding a renamed tool rather than raising an error.\n\n## Contributing\n\n**Contributions are welcome, and new service adapters most of all** — Lidarr,\nEmby and Deluge would all be accepted today, and\n[the list says so in advance](CONTRIBUTING.md#what-would-be-accepted-today),\nalong with the ones that would not be. An adapter is deliberately the most\nself-contained thing in the codebase. Two things to know first: not every\nservice qualifies, and the bar is written down rather than decided per pull\nrequest — [which services qualify](CONTRIBUTING.md#which-services-qualify). And\n**I cannot test a service I do not run**, so the second bar is that you tested\nit against your own live instance and the PR says what you tested and against\nwhich version.\n\n**One adapter remains unverified: qBittorrent.** The maintainer runs neither\nPlex nor qBittorrent — testing means running a build against your own server\nand reporting what worked. [Plex](../../issues/180) has since been verified\nagainst a live Plex Media Server 1.43.3.10896 by a volunteer tester;\n[qBittorrent](../../issues/147) has shipped but still waits on the same kind\nof report. [The design behind Plex, and what else is on the\nlist](CONTRIBUTING.md#what-would-be-accepted-today).\n\n**AI-assisted contributions are welcome**, held to the same bar and no other;\narr-mcp is itself built with a coding agent. Point yours at\n[CONTRIBUTING.md](CONTRIBUTING.md#if-you-are-working-with-a-coding-agent).\n\n**Missing a tool?** [Open an issue](../../issues/new/choose) describing the\nquestion you could not get answered rather than the tool you think should\nexist. Often the answer is a new parameter on one that already exists — and\nwhen it genuinely needs a new tool, the question is what tells us so.\n\n## Security\n\narr-mcp is **not designed to be exposed to the internet.** The `/mcp` endpoint\nrequires a bearer token because \"LAN-only\" is a network assumption rather than a\nsecurity control — it fronts every service credential you configure and, once enabled, file\ndeletion, and a home network contains guest phones and IoT devices. Put it\nbehind a reverse proxy with TLS if it needs to leave the LAN, and pin\n`allowed_hosts` if you do.\n\nBeyond the network: writes are off until you enable them, every write is\npreviewed and confirmed before it acts, and everything a service returns is\nfenced as data rather than instruction. [Security](docs/security.md) walks all\nof it against the OWASP MCP Top 10 — and is equally explicit about what it does\nnot solve. Found something? [SECURITY.md](SECURITY.md).\n\n## Thanks\n\narr-mcp is glue; the hard parts belong to other people. Every service it speaks\nto is free software maintained largely by volunteers — [Radarr](https://radarr.video),\n[Sonarr](https://sonarr.tv), [Prowlarr](https://prowlarr.com),\n[Bazarr](https://www.bazarr.media), [Jellyfin](https://jellyfin.org),\n[Seerr](https://github.com/seerr-team/seerr), [SABnzbd](https://sabnzbd.org),\n[Transmission](https://transmissionbt.com), [qBittorrent](https://www.qbittorrent.org) — as are the libraries it is built\non: [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk),\n[Hono](https://hono.dev), [Zod](https://zod.dev), [Pino](https://getpino.io),\n[Vitest](https://vitest.dev), [yaml](https://eemeli.org/yaml/) and\n[TypeScript](https://www.typescriptlang.org). If you find arr-mcp useful,\nconsider supporting them first.\n\nWhen you enable the [IMDb dataset](docs/imdb.md): information courtesy of\n[IMDb](https://www.imdb.com), used with permission, for personal and\nnon-commercial use.\n\n## Licence\n\n[MIT](LICENSE)\n",
  "bytes": 11368,
  "sha": "a6cb7f51470c009469bb26dfc160b1243b0a9b3de6c1b4b775e06620d77824be",
  "repo_slug": "bardesss/arr-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_bardesss_arr_mcp_83c2d9ca/readme"
}