Skip to main content
Glama
aderaaij

mcp-mediastack

by aderaaij
README.md
# mcp-mediastack

An [MCP](https://modelcontextprotocol.io/) server that provides 50 tools for monitoring and managing a Docker-based media stack. Built with [FastMCP](https://github.com/jlowin/fastmcp) and [httpx](https://www.python-httpx.org/).

## Supported Services

- **Sonarr** - TV series management
- **Radarr** - Movie management
- **SABnzbd** - Usenet downloader
- **qBittorrent** - Torrent client
- **Prowlarr** - Indexer management
- **Readarr** - Book management
- **Bazarr** - Subtitle management
- **Seerr** - Media requests
- **Gluetun** - VPN status monitoring
- **Scoutarr** - Batch upgrade searches (space-saver sweep)
- **Cleanuparr** - Stalled-download cleanup
- Plus a **space-saver sweep progress** tool built on Radarr/Sonarr tags

## Quick Start

### Docker Run

```bash
docker run -d \
  --name mediastack-mcp \
  -p 8888:8888 \
  -e MCP_TRANSPORT=sse \
  -e NAS_HOST=192.168.1.100 \
  -e SONARR_API_KEY=your_key \
  -e RADARR_API_KEY=your_key \
  -e SABNZBD_API_KEY=your_key \
  ghcr.io/aderaaij/mcp-mediastack:latest
```

### Docker Compose

```yaml
services:
  mediastack-mcp:
    image: ghcr.io/aderaaij/mcp-mediastack:latest
    container_name: mediastack-mcp
    restart: unless-stopped
    ports:
      - 8888:8888
    environment:
      - MCP_TRANSPORT=sse
      - MCP_PORT=8888
      - NAS_HOST=192.168.1.100
      - SONARR_API_KEY=${SONARR_API_KEY}
      - RADARR_API_KEY=${RADARR_API_KEY}
      - SABNZBD_API_KEY=${SABNZBD_API_KEY}
      - PROWLARR_API_KEY=${PROWLARR_API_KEY}
      - READARR_API_KEY=${READARR_API_KEY}
      - BAZARR_API_KEY=${BAZARR_API_KEY}
      - SEERR_API_KEY=${SEERR_API_KEY}
      - QBITTORRENT_USERNAME=${QBITTORRENT_USERNAME}
      - QBITTORRENT_PASSWORD=${QBITTORRENT_PASSWORD}
```

## Environment Variables

| Variable | Default | Description |
|---|---|---|
| `MCP_TRANSPORT` | `stdio` | Transport mode: `stdio` or `sse` |
| `MCP_PORT` | `8888` | Port for SSE transport |
| `NAS_HOST` | `192.168.1.100` | IP/hostname of your server running the media stack |
| `SONARR_API_KEY` | | Sonarr API key (Settings > General) |
| `SONARR_PORT` | `8989` | Sonarr port |
| `RADARR_API_KEY` | | Radarr API key |
| `RADARR_PORT` | `7878` | Radarr port |
| `SABNZBD_API_KEY` | | SABnzbd API key |
| `SABNZBD_PORT` | `8080` | SABnzbd port |
| `QBITTORRENT_USERNAME` | `admin` | qBittorrent username |
| `QBITTORRENT_PASSWORD` | `adminadmin` | qBittorrent password |
| `QBITTORRENT_PORT` | `8090` | qBittorrent port |
| `PROWLARR_API_KEY` | | Prowlarr API key |
| `PROWLARR_PORT` | `9696` | Prowlarr port |
| `READARR_API_KEY` | | Readarr API key |
| `READARR_PORT` | `8787` | Readarr port |
| `BAZARR_API_KEY` | | Bazarr API key |
| `BAZARR_PORT` | `6767` | Bazarr port |
| `SEERR_API_KEY` | | Seerr API key |
| `SEERR_PORT` | `5055` | Seerr port |
| `GLUETUN_PORT` | `8005` | Gluetun control API port |
| `SCOUTARR_PORT` | `5839` | Scoutarr port — set explicitly to enable the Scoutarr tools |
| `CLEANUPARR_PORT` | `11011` | Cleanuparr port — set explicitly to enable the Cleanuparr tools |
| `ENABLED_SERVICES` | | Only load these services (comma-separated, e.g. `sonarr,radarr`) |
| `DISABLED_SERVICES` | | Skip these services (comma-separated, e.g. `vpn,qbittorrent`) |

### Selective tool loading

Tools are automatically loaded based on which API keys are set. Only set the keys for the services you use — tools for unconfigured services won't be registered.

- **API key services** (Sonarr, Radarr, Readarr, Prowlarr, Bazarr, SABnzbd, Seerr): enabled when their API key is non-empty
- **qBittorrent and VPN**: enabled by default (no API key). Use `DISABLED_SERVICES=vpn,qbittorrent` to disable
- **Scoutarr and Cleanuparr**: keyless — enabled only when `SCOUTARR_PORT` / `CLEANUPARR_PORT` is set explicitly
- **Space-saver**: enabled when both the Sonarr and Radarr API keys are set
- **`ENABLED_SERVICES`**: override auto-detection with an explicit whitelist (e.g. `ENABLED_SERVICES=sonarr,radarr`)

## Tools

### Monitoring (32 tools)

| Tool | Description |
|---|---|
| `get_system_overview` | Combined status of all services |
| `get_vpn_status` | Current VPN connection info via Gluetun |
| `check_vpn_health` | Verify VPN is working (IP leak check) |
| `get_sonarr_status` | Sonarr system status |
| `get_sonarr_queue` | Active download queue |
| `get_sonarr_calendar` | Upcoming episodes |
| `get_sonarr_activity` | Recent download history |
| `get_sonarr_missing` | Missing episodes |
| `search_sonarr_series` | Search existing library |
| `get_sonarr_library_stats` | Library statistics |
| `get_radarr_status` | Radarr system status |
| `get_radarr_queue` | Active download queue |
| `get_radarr_calendar` | Upcoming movies |
| `get_radarr_activity` | Recent download history |
| `get_radarr_missing` | Missing movies |
| `search_radarr_movies` | Search existing library |
| `get_radarr_library_stats` | Library statistics |
| `get_sabnzbd_status` | SABnzbd queue and status |
| `get_sabnzbd_history` | Download history |
| `get_qbittorrent_status` | qBittorrent transfer info |
| `get_qbittorrent_torrents` | List torrents with filters |
| `get_prowlarr_status` | Indexer status and stats |
| `get_readarr_status` | Readarr system status |
| `get_readarr_queue` | Readarr download queue |
| `get_bazarr_status` | Bazarr system status |
| `get_bazarr_wanted` | Missing subtitles |
| `get_seerr_status` | Pending requests and stats |
| `get_scoutarr_status` | Scoutarr instance connectivity and sweep config |
| `get_cleanuparr_status` | Cleanuparr app status and download-client health |
| `get_cleanuparr_events` | Recent strikes, removals and re-searches |
| `get_space_saver_status` | Space-saver sweep progress: searched/remaining counts, sizes, largest remaining items |

### Actions (18 tools)

| Tool | Description |
|---|---|
| `lookup_sonarr_series` | Search for new series to add |
| `add_sonarr_series` | Add series by TVDB ID |
| `sonarr_search_missing` | Trigger search for missing episodes |
| `sonarr_remove_from_queue` | Remove stuck queue items |
| `lookup_radarr_movies` | Search for new movies to add |
| `add_radarr_movie` | Add movie by TMDB ID |
| `radarr_search_missing` | Trigger search for missing movies |
| `radarr_remove_from_queue` | Remove stuck queue items |
| `send_arr_command` | Send a command to Sonarr/Radarr/Readarr (e.g. RefreshSeries, CheckHealth) |
| `run_scoutarr_sweep` | Trigger a Scoutarr sweep run (all instances, blocks ~4-5 min) |
| `sabnzbd_pause_resume` | Pause or resume SABnzbd |
| `sabnzbd_delete_job` | Delete a download job |
| `sabnzbd_retry_failed` | Retry a failed download |
| `qbittorrent_pause_torrents` | Pause torrents |
| `qbittorrent_resume_torrents` | Resume torrents |
| `qbittorrent_delete_torrents` | Delete torrents |
| `seerr_approve_request` | Approve a media request |
| `seerr_decline_request` | Decline a media request |

## Claude Desktop Integration

Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):

### Direct (stdio, same machine)

```json
{
  "mcpServers": {
    "mediastack": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "NAS_HOST=192.168.1.100",
        "-e", "SONARR_API_KEY=your_key",
        "ghcr.io/aderaaij/mcp-mediastack:latest"
      ]
    }
  }
}
```

### Remote (SSE via mcp-remote)

If the server is running on a remote host with SSE transport:

```json
{
  "mcpServers": {
    "mediastack": {
      "command": "npx",
      "args": ["mcp-remote", "http://your-server:8888/sse"]
    }
  }
}
```

## Known Quirks

- **httpx params**: Never pass `params={}` (empty dict) to httpx — it strips query parameters from the URL. Only pass `params` when non-empty.
- **Seerr titles**: Seerr requests don't include titles directly. The server resolves them via TMDB lookups using the media's TMDB ID.
- **qBittorrent auth**: Uses session-based cookie auth, not API keys. The server handles login automatically.

## Development

```bash
# Install dependencies
uv sync

# Run locally (stdio mode)
python -m mcp_mediastack

# Run locally (SSE mode)
MCP_TRANSPORT=sse python -m mcp_mediastack
```

## License

MIT