MCP server for a self-hosted arr media stack
- ✓Open-source license (Apache-2.0)
- ✓Actively maintained (<30d)
- ✓Clear description
- ✓Documented (README)
claude mcp add oraclarr -- python -m oraclarr{
"mcpServers": {
"oraclarr": {
"command": "python",
"args": ["-m", "oraclarr_mcp"],
"env": {
"ORACLARR_SONARR_URL": "<oraclarr_sonarr_url>",
"ORACLARR_SONARR_API_KEY": "<oraclarr_sonarr_api_key>",
"ORACLARR_SONARR_ANIME_URL": "<oraclarr_sonarr_anime_url>",
"ORACLARR_SONARR_ANIME_API_KEY": "<oraclarr_sonarr_anime_api_key>",
"ORACLARR_QBITTORRENT_URL": "<oraclarr_qbittorrent_url>",
"ORACLARR_QBITTORRENT_USERNAME": "<oraclarr_qbittorrent_username>"
}
}
}
}ORACLARR_SONARR_URLORACLARR_SONARR_API_KEYORACLARR_SONARR_ANIME_URLORACLARR_SONARR_ANIME_API_KEYORACLARR_QBITTORRENT_URLORACLARR_QBITTORRENT_USERNAMEResumen de MCP Servers
<!-- mcp-name: io.github.bdog720/oraclarr -->
<div align="center">
# Oraclarr
**Ask your media stack what's going on, in plain language.**
A locally-run, read-only [MCP](https://modelcontextprotocol.io) server that lets an LLM client (Claude Code, Claude Desktop) diagnose a self-hosted *arr media stack.





</div>
---
## What it does
Oraclarr gives a language model one place to answer the operational "why" questions that normally mean tabbing through six web UIs. It aggregates across your services and returns a single, structured answer without changing anything (it is strictly read-only in this phase).
Covered now: **Sonarr**, **Radarr**, **Sportarr**, **Prowlarr**, **qBittorrent**, **Tdarr**, **Profilarr**, and **Jellyfin** — including **multiple instances of the same type** (e.g. a separate anime or 4K Sonarr/Radarr). Every tool fans out across all the instances you define and reports each one separately.
## In practice
Once registered, you just ask your MCP client. Oraclarr picks the right tool and answers:
| You ask… | Oraclarr runs | …and tells you |
|----------|---------------|----------------|
| "Is anything in my stack down?" | `stack_health` | which services are unreachable, unhealthy, or low on disk |
| "Why hasn't the new episode of *X* downloaded yet?" | `diagnose` | whether *X* is in your library, sitting in the download queue, or still on the wanted list |
| "Why did a sub-only release get grabbed when I only allow English dubs?" | `explain_decision` | the release that was grabbed, its custom-format score, and the language formats that matched |
| "Why does Profilarr keep upgrading stuff that already looks fine?" | `explain_decision` + `get_quality_config` | the profile's cutoff and upgrade thresholds next to the scores of recent grabs |
| "What's stuck downloading right now?" | `get_queues` | a unified queue with progress and stall flags |
| "Is the Jellyfin library scan finished, and is anyone transcoding?" | `get_library` | scan state and progress per library, failed tasks, and who is playing what (with transcode reasons) |
## Tools
All read-only and outcome-oriented (not one-per-endpoint, which keeps the model accurate):
| Tool | Answers |
|------|---------|
| `stack_health` | Is anything down / unhealthy / low on disk? |
| `get_queues` | Unified active downloads (arr queue ↔ qBittorrent), stalls |
| `diagnose` | Where is *X* in the pipeline / why isn't it here yet? |
| `explain_decision` | Why was *X* grabbed or being upgraded? (profile, custom formats, grab history) |
| `get_quality_config` | Quality profiles, custom formats, release profiles, Profilarr sync state |
| `get_history` | Recent grabs / imports / failures |
| `get_wanted` | What's missing / cutoff-unmet? |
| `search_media` | Do I have *X*, what's its status? |
| `get_indexers` | Which indexers are failing? |
| `get_transcodes` | What's transcoding / stuck? |
| `get_upcoming` | What's airing or releasing soon, and will it land? (up to 90 days) |
| `get_library` | Jellyfin libraries, scan progress, tasks, playback and transcodes, recent additions, name search |
## Install
There are two ways to run Oraclarr. Pick one:
- **🐳 Docker (recommended).** A small always-on container next to your arr stack. Works with Dockge, Portainer, Unraid and plain `docker compose`.
- **🐍 Python (uv).** Runs directly on your machine with no container. Handy for local development, or if you don't use Docker.
Either way, every setting is an environment variable that starts with `ORACLARR_`. With Docker that means one `.env` file next to the compose file, and Dockge and Portainer show both in their editors. Start from [`.env.example`](.env.example). [Configuration](#configuration) lists every variable. Your `.env` is never committed.
---
### Option A — Docker (recommended)
Oraclarr runs as a long-running container that serves MCP over HTTP at `http://<host>:7979/mcp`. You need two files in one folder: `docker-compose.yml` and `.env`.
**Using a stack manager (Dockge, Portainer, etc.):** create a new stack, paste the compose below into the editor, and paste your settings into the stack's `.env`. Hit deploy. Portainer saves the variables from its web editor as `stack.env`, so in Portainer change the compose line to `env_file: stack.env`.
**Using the command line:**
```bash
cp docker-compose.example.yml docker-compose.yml
cp .env.example .env # then fill in your URLs and keys
docker compose up -d
```
This is the compose file. You don't edit it when you add or remove a service:
```yaml
services:
oraclarr:
image: ghcr.io/bdog720/oraclarr-mcp:latest
container_name: oraclarr
restart: unless-stopped
ports:
- "7979:7979" # left side is the host port; change it if 7979 is taken
env_file: .env
```
Then [connect Claude Desktop](#connect-claude-desktop).
---
### Option B — Python (uv)
Run Oraclarr directly, no Docker. Requires Python 3.12+ and [`uv`](https://docs.astral.sh/uv/).
The package is on PyPI as [`oraclarr-mcp`](https://pypi.org/project/oraclarr-mcp/). It speaks MCP over **stdio**, so your client starts the process and passes the settings in its `env` block:
```json
"oraclarr": {
"command": "uvx",
"args": ["oraclarr-mcp"],
"env": {
"ORACLARR_SONARR_URL": "http://192.168.1.10:8989",
"ORACLARR_SONARR_API_KEY": "your-key",
"ORACLARR_RADARR_URL": "http://192.168.1.10:7878",
"ORACLARR_RADARR_API_KEY": "your-key"
}
}
```
**From a clone (for development):** put the same `ORACLARR_*` lines in a `.env` in the repo folder (it's read at startup), then:
```bash
uv sync
uv run python -m oraclarr_mcp
```
In a client config, use `"command": "uv"`, `"args": ["run", "python", "-m", "oraclarr_mcp"]` and a `"cwd"` pointing at the repo.
---
### Connect Claude Desktop
*(For Option A / Docker. Option B registers itself with the JSON snippet above.)*
Use the **`mcp-remote` bridge** in `claude_desktop_config.json`. It runs locally as
a Claude Desktop "local MCP server", so it can reach the container on your LAN
(requires Node.js / `npx`):
```json
{
"mcpServers": {
"oraclarr": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://<host>:7979/mcp", "--allow-http"]
}
}
}
```
Replace `<host>` with the IP or hostname of the machine running the container.
> **Why `--allow-http`?** Recent versions of `mcp-remote` reject plain `http://` URLs
> unless the host is `localhost`. Without this flag the bridge exits immediately and
> Claude Desktop shows the server as "disconnected" — even though the server itself is
> reachable. The flag is safe here: the traffic stays on your trusted LAN.
> **Why not the native "Add custom connector"?** Custom connectors connect to your
> server **from Anthropic's cloud**, not from your machine — so the URL must be a
> publicly reachable **HTTPS** endpoint (a `http://` LAN/localhost URL is rejected).
> Pointing it at a homelab box means exposing this **unauthenticated read-only**
> service to the internet, which we don't recommend until authentication lands (a
> later phase). If you want it anyway, put a reverse proxy (Caddy/nginx) or tunnel
> (Cloudflare Tunnel, Tailscale Funnel) with TLS in front and add your own auth.
> **Security:** the service is unauthenticated read-only MCP. Deploy on a trusted
> LAN only and do not expose port 7979 to the internet. Authentication is a later
> phase.
### Transport settings (Docker only)
These apply to the **Docker** container only. The image already sets sensible
defaults, so **you normally don't touch them** — the table is here for reference.
The Python path (Option B) always uses stdio and ignores these entirely.
| Variable | Default | What it does |
|---|---|---|
| `ORACLARR_TRANSPORT` | `http` | How clients reach the server. `http` = long-running service (Docker). `stdio` = the client launches the process (the Python path). You don't normally set this by hand — your install method picks it. |
| `ORACLARR_HTTP_HOST` | `0.0.0.0` | Which network interface to listen on. `0.0.0.0` means "reachable on your LAN" — leave as-is for Docker. |
| `ORACLARR_HTTP_PORT` | `7979` | Port *inside* the container. To change the port you reach it on, edit the `ports:` line in the compose instead. |
| `ORACLARR_CONFIG` | `/config/config.yaml` | Where the container looks for an optional config.yaml. Leave as-is. |
## Configuration
Each service is an *instance* with a name you choose. Its settings are variables named `ORACLARR_<NAME>_<FIELD>`, and an instance exists as soon as its `_URL` is set:
```
ORACLARR_SONARR_URL=http://192.168.1.10:8989
ORACLARR_SONARR_API_KEY=your-key
ORACLARR_SONARR_ANIME_TYPE=sonarr # a second Sonarr, named sonarr-anime
ORACLARR_SONARR_ANIME_URL=http://192.168.1.10:8990
ORACLARR_SONARR_ANIME_API_KEY=your-key
ORACLARR_QBITTORRENT_URL=http://192.168.1.10:8080
ORACLARR_QBITTORRENT_USERNAME=admin
ORACLARR_QBITTORRENT_PASSWORD=your-password
```
| Field | Needed for |
|---|---|
| `_URL` | every instance |
| `_TYPE` | only when the name isn't a service type. Types: `sonarr`, `radarr`, `sportarr`, `prowlarr`, `qbittorrent`, `tdarr`, `profilarr`, `jellyfin` |
| `_API_KEY` | Sonarr, Radarr, Sportarr, Prowlarr, Profilarr, Jellyfin |
| `_USERNAME`, `_PASSWORD` | qBittorrent |
| `_ENABLED` | optional; `false` switches an instance off without deleting its lines |
Underscores in the name become dashes in the instance name, so `SONARR_ANIME` shows up as `sonarr-anime`. Blank values count as unset, so you can keep lines for services you don't run. A misspelled `ORACLARR_` variable stops the container with a message that names it, instead of failing quietly later.
ServerLo que la gente pregunta sobre oraclarr
¿Qué es bdog720/oraclarr?
+
bdog720/oraclarr es mcp servers para el ecosistema de Claude AI. MCP server for a self-hosted arr media stack Tiene 0 estrellas en GitHub y su última actualización registrada es del 2026-10-11.
¿Cómo se instala oraclarr?
+
Puedes instalar oraclarr clonando el repositorio (https://github.com/bdog720/oraclarr) o siguiendo las instrucciones del README en GitHub. ClaudeWave también te ofrece bloques de instalación rápida en esta misma página.
¿Es seguro usar bdog720/oraclarr?
+
Nuestro agente de seguridad ha analizado bdog720/oraclarr y le ha asignado un Trust Score de 87/100 (tier: Trusted). Revisa el desglose completo de comprobaciones superadas y flags en esta página.
¿Quién mantiene bdog720/oraclarr?
+
bdog720/oraclarr es mantenido por bdog720. La última actividad registrada en GitHub es del 2026-10-11, con 0 issues abiertos.
¿Hay alternativas a oraclarr?
+
Sí. En ClaudeWave puedes explorar mcp servers similares en /categories/mcp, ordenados por popularidad o actividad reciente.
Despliega oraclarr en tu cloud
Lleva este repo a producción en minutos. Cada plataforma genera su propio entorno con variables de entorno editables.
¿Mantienes este repo? Añade un badge a tu README
Pega el badge en tu README de GitHub para mostrar que está auditado por ClaudeWave. Cada badge enlaza de vuelta a esta página y muestra el Trust Score actual.
[](https://claudewave.com/repo/bdog720-oraclarr)<a href="https://claudewave.com/repo/bdog720-oraclarr"><img src="https://claudewave.com/api/badge/bdog720-oraclarr" alt="Featured on ClaudeWave: bdog720/oraclarr" width="320" height="64" /></a>Más MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
Reverse engineer anything with agents, from app behavior down to native binaries.
An open-source AI agent that brings the power of Gemini directly into your terminal.
Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl! Don't be shy, join here: https://discord.gg/EMgGbDceNQ and follow here for daily tips and tricks: https://x.com/Scrapling_dev