An MCP server exposing Sonarr, Radarr, Prowlarr, and Overseerr to an LLM client. Connect Claude or another MCP-compatible LLM to your media stack and ask it to search for content, manage your...
Overview
An MCP server exposing Sonarr, Radarr, Prowlarr, and Overseerr to an LLM client. Connect Claude or another MCP-compatible LLM to your media stack and ask it to search for content, manage your library, check download status, and more — all via natural language. This server reaches Sonarr and Radarr at their /api/v3 endpoints, and Prowlarr at /api/v1. (Note: Sonarr's published documentation often references "v5" in the URL, but that is the application version, not the API version — use v3.) This server grants any connected MCP client full read/write access to your media stack, including the ability to permanently delete series, movies, and files on disk. Any LLM you connect can invoke destructive tools. Understand this before enabling it, and configure your MCP client with appropriate safeguards. Clone the repository, install dependencies, and build: The server will start on a stdio interface, expecting MCP protocol messages.
README
servarr-mcp
An MCP server exposing Sonarr, Radarr, Prowlarr, and Overseerr to an LLM client. Connect Claude or another MCP-compatible LLM to your media stack and ask it to search for content, manage your library, check download status, and more — all via natural language.
This server reaches Sonarr and Radarr at their /api/v3 endpoints, and Prowlarr at /api/v1. (Note: Sonarr’s published documentation often references “v5” in the URL, but that is the application version, not the API version — use v3.)
Important: This server grants any connected MCP client full read/write access to your media stack, including the ability to permanently delete series, movies, and files on disk. Any LLM you connect can invoke destructive tools. Understand this before enabling it, and configure your MCP client with appropriate safeguards.
Install
Prerequisites: Node.js 20 or later.
From Source
Clone the repository, install dependencies, and build:
git clone https://github.com/jfms7s/servarr-mcp.git
cd servarr-mcp
npm ci
npm run build
Then run the server:
node dist/index.js
The server will start on a stdio interface, expecting MCP protocol messages. Use this command in your MCP client’s configuration (see the Claude Desktop / Claude Code Setup section below).
With Docker
Use the published container image (linux/amd64 and linux/arm64), pinned to a release tag such as v0.1.2, or latest:
docker run --rm -p 3000:3000 \
-e SERVARR_MCP_TOKEN=a-long-random-secret \
-e SONARR_URL=http://sonarr:8989 \
-e SONARR_API_KEY=your-sonarr-api-key \
-e RADARR_URL=http://radarr:7878 \
-e RADARR_API_KEY=your-radarr-api-key \
-e PROWLARR_URL=http://prowlarr:9696 \
-e PROWLARR_API_KEY=your-prowlarr-api-key \
-e OVERSEERR_URL=http://overseerr:5055 \
-e OVERSEERR_API_KEY=your-overseerr-api-key \
ghcr.io/jfms7s/servarr-mcp:v0.1.2
Note: The image defaults to the HTTP transport (SERVARR_MCP_TRANSPORT=http), which requires SERVARR_MCP_TOKEN — without it the container exits at startup. The URLs must be reachable from inside the container: localhost there is the container itself, not your host. Use the arr containers’ names on a shared Docker network (as above), or their LAN addresses. For many variables, use --env-file:
docker run --rm -p 3000:3000 --env-file .env ghcr.io/jfms7s/servarr-mcp:latest
Where .env contains your configuration lines (one per line: VAR_NAME=value).
Building the Docker Image Locally
If you want to build the image locally:
docker build -t servarr-mcp .
docker run --rm -p 3000:3000 --env-file .env servarr-mcp
Configuration
The server reads configuration from environment variables. Each product is independently optional — you can configure only the ones you use. The server will fail to start only if no products are configured.
| Variable | Example | Required | Purpose |
|---|---|---|---|
SONARR_URL |
http://localhost:8989 |
No | Base URL of your Sonarr instance |
SONARR_API_KEY |
abc123def456 |
Only if SONARR_URL is set |
API key from Sonarr Settings → General |
RADARR_URL |
http://localhost:7878 |
No | Base URL of your Radarr instance |
RADARR_API_KEY |
abc123def456 |
Only if RADARR_URL is set |
API key from Radarr Settings → General |
PROWLARR_URL |
http://localhost:9696 |
No | Base URL of your Prowlarr instance |
PROWLARR_API_KEY |
abc123def456 |
Only if PROWLARR_URL is set |
API key from Prowlarr Settings → General |
OVERSEERR_URL |
http://localhost:5055 |
No | Base URL of your Overseerr instance |
OVERSEERR_API_KEY |
abc123def456 |
Only if OVERSEERR_URL is set |
API key from Overseerr Settings → General |
SERVARR_MCP_TRANSPORT |
stdio or http or both |
No | Transport mode (default stdio) |
SERVARR_MCP_PORT |
3000 |
No | Port for HTTP transport (default 3000) |
SERVARR_MCP_TOKEN |
a-long-random-secret |
Required if transport is http or both |
Bearer token for HTTP client authentication |
Example: Sonarr and Prowlarr only
If you only want to use Sonarr and Prowlarr, set only these:
export SONARR_URL=http://localhost:8989
export SONARR_API_KEY=your-sonarr-key
export PROWLARR_URL=http://localhost:9696
export PROWLARR_API_KEY=your-prowlarr-key
node dist/index.js
The server will register 42 tools (28 Sonarr + 14 Prowlarr) and start normally. Radarr and Overseerr tools will not be available.
Claude Desktop / Claude Code Setup
From Source
Add this to your claude_desktop_config.json or Claude Code MCP server configuration:
{
"mcpServers": {
"servarr": {
"command": "node",
"args": ["/path/to/servarr-mcp/dist/index.js"],
"env": {
"SONARR_URL": "http://localhost:8989",
"SONARR_API_KEY": "your-sonarr-api-key",
"RADARR_URL": "http://localhost:7878",
"RADARR_API_KEY": "your-radarr-api-key",
"PROWLARR_URL": "http://localhost:9696",
"PROWLARR_API_KEY": "your-prowlarr-api-key",
"OVERSEERR_URL": "http://localhost:5055",
"OVERSEERR_API_KEY": "your-overseerr-api-key"
}
}
}
}
Replace /path/to/servarr-mcp/dist/index.js with the absolute path to the built server in your cloned repository. Replace your-*-api-key with your actual API keys from each application’s Settings → General → API Key.
With Docker
{
"mcpServers": {
"servarr": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"--add-host=host.docker.internal:host-gateway",
"--env",
"SERVARR_MCP_TRANSPORT=stdio",
"--env",
"SONARR_URL=http://host.docker.internal:8989",
"--env",
"SONARR_API_KEY=your-sonarr-api-key",
"--env",
"RADARR_URL=http://host.docker.internal:7878",
"--env",
"RADARR_API_KEY=your-radarr-api-key",
"--env",
"PROWLARR_URL=http://host.docker.internal:9696",
"--env",
"PROWLARR_API_KEY=your-prowlarr-api-key",
"--env",
"OVERSEERR_URL=http://host.docker.internal:5055",
"--env",
"OVERSEERR_API_KEY=your-overseerr-api-key",
"ghcr.io/jfms7s/servarr-mcp:latest"
]
}
}
}
Two things differ from the source setup. SERVARR_MCP_TRANSPORT=stdio is required: the image defaults to HTTP, and without the override it would neither speak stdio nor start at all (HTTP needs a token). And localhost inside the container is the container itself, so the arr apps on your host are reached through host.docker.internal, which the --add-host flag maps to the host on Linux (Docker Desktop provides it already). Replace your-*-api-key with your actual API keys from each application’s Settings → General → API Key.
Remote / HTTP Deployment
For a remote setup (e.g., accessing Sonarr from a separate machine), use the HTTP transport:
From Source
export SERVARR_MCP_TRANSPORT=http
export SERVARR_MCP_PORT=3000
export SERVARR_MCP_TOKEN=your-shared-bearer-token
node dist/index.js
With Docker
docker run --rm -p 3000:3000 \
-e SERVARR_MCP_TRANSPORT=http \
-e SERVARR_MCP_PORT=3000 \
-e SERVARR_MCP_TOKEN=your-shared-bearer-token \
-e SONARR_URL=http://sonarr:8989 \
-e SONARR_API_KEY=your-sonarr-api-key \
ghcr.io/jfms7s/servarr-mcp:latest
The server will listen on the specified port on all interfaces, authenticated with a single bearer token. Control which interfaces can reach it using your container networking, firewall, or reverse proxy configuration.
Two routes are served:
| Route | Auth | Purpose |
|---|---|---|
/mcp |
Bearer token required | The MCP endpoint |
/healthz |
None | Liveness/readiness probes; returns 200 ok |
/healthz is deliberately unauthenticated so an orchestrator’s probes can reach it — a probe cannot present a token, and /mcp answers an unauthenticated request with 401, which a probe reads as a failing container. It reports only that this process is still serving. It deliberately does not check your Sonarr, Radarr or Prowlarr instances, so an outage in one of those will not get this container restarted or pulled out of service.
⚠️ Security Warning
The HTTP transport is dangerous. It uses a single shared bearer token for authentication and grants full read/write access to your entire media stack, including the ability to delete series, movies, and files on disk. Never expose this over the open internet. The HTTP interface must be:
- Behind a VPN
- Protected by a reverse proxy with additional authentication (e.g., basic auth, OAuth)
- On a trusted LAN only
A compromised bearer token gives an attacker complete control to delete your library. Use HTTP only in environments you fully control.
Tools
This server exposes 106 tools across the four products.
Sonarr (33 tools)
| Tool | Purpose |
|---|---|
sonarr_list_series |
List series, filterable by root folder, genre, series type, title and monitored state; paginated (default 50) |
sonarr_get_series |
Get the full record for one series, including all seasons |
sonarr_lookup_series |
Search TheTVDB for series matching a search term |
sonarr_add_series |
Add a new series to Sonarr |
sonarr_delete_series |
Destructive: Remove a series from Sonarr; deleting files requires an explicit confirm flag |
sonarr_update_series |
Update series settings, including root folder and series type, optionally moving files on disk |
sonarr_list_episodes |
List episodes for a series or season |
sonarr_get_episode |
Get the full record for one episode |
sonarr_monitor_episodes |
Set monitored state for one or more episodes |
sonarr_list_episode_files |
List downloaded episode files for a series |
sonarr_delete_episode_file |
Destructive: Permanently delete an episode file |
sonarr_get_queue |
List items currently downloading or awaiting import |
sonarr_delete_queue_item |
Destructive: Remove an item from the download queue |
sonarr_search_releases |
Interactive search for an episode or season pack, with Sonarr’s rank and rejection reasons |
sonarr_grab_release |
Download a specific release from a search; Sonarr tracks and imports it |
sonarr_get_calendar |
List episodes airing in a date range |
sonarr_get_history |
List download, import, and grab event history |
sonarr_get_wanted_missing |
List wanted but missing episodes |
sonarr_get_blocklist |
List releases on the blocklist |
sonarr_delete_blocklist_item |
Destructive: Remove a release from the blocklist |
sonarr_run_command |
Trigger a background command (search, rescan, refresh) |
sonarr_get_command |
Poll the status of a background command |
sonarr_list_quality_profiles |
List available quality profiles |
sonarr_bulk_edit_series |
Change root folder, quality profile, series type, monitored state or tags on many series at once |
sonarr_list_unmapped_folders |
List folders on disk under each root folder that Sonarr has no series for |
sonarr_import_folder |
Scan a folder and import any episode files found into an existing series |
sonarr_get_rename_preview |
Preview the folder and file names a rename would produce, without renaming |
sonarr_find_duplicate_series |
Report series present under more than one root folder |
sonarr_list_root_folders |
List configured root folders, including unmapped folders |
sonarr_list_tags |
List all tags available for series organization |
sonarr_get_system_status |
Get Sonarr version and system information |
sonarr_get_health |
Check Sonarr health status and warnings |
sonarr_get_disk_space |
List disk space on drives containing series |
Radarr (31 tools)
| Tool | Purpose |
|---|---|
radarr_list_movies |
List movies, filterable by root folder, genre, title, file and monitored state; paginated (default 50) |
radarr_get_movie |
Get the full record for one movie |
radarr_lookup_movie |
Search TMDB for movies matching a search term |
radarr_add_movie |
Add a new movie to Radarr |
radarr_update_movie |
Update movie settings, including root folder, optionally moving files on disk |
radarr_delete_movie |
Destructive: Remove a movie from Radarr; deleting files requires an explicit confirm flag |
radarr_list_movie_files |
List downloaded movie files for a movie |
radarr_delete_movie_file |
Destructive: Permanently delete a movie file |
radarr_get_calendar |
List movies with releases in a date range |
radarr_get_queue |
List items currently downloading or awaiting import |
radarr_delete_queue_item |
Destructive: Remove an item from the download queue |
radarr_search_releases |
Interactive search for a movie, with Radarr’s rank and rejection reasons |
radarr_grab_release |
Download a specific release from a search; Radarr tracks and imports it |
radarr_get_history |
List download, import, and grab event history |
radarr_get_wanted_missing |
List wanted but missing movies |
radarr_get_blocklist |
List releases on the blocklist |
radarr_delete_blocklist_item |
Destructive: Remove a release from the blocklist |
radarr_list_collections |
List all movie collections |
radarr_run_command |
Trigger a background command (search, rescan, refresh) |
radarr_get_command |
Poll the status of a background command |
radarr_list_quality_profiles |
List available quality profiles |
radarr_bulk_edit_movies |
Change root folder, quality profile, monitored state or tags on many movies at once |
radarr_list_unmapped_folders |
List folders on disk under each root folder that Radarr has no movie for |
radarr_import_folder |
Scan a folder and import any movie file found into an existing movie |
radarr_get_rename_preview |
Preview the folder and file names a rename would produce, without renaming |
radarr_find_duplicate_movies |
Report films present under more than one root folder |
radarr_list_root_folders |
List configured root folders, including unmapped folders |
radarr_list_tags |
List all tags available for movie organization |
radarr_get_system_status |
Get Radarr version and system information |
radarr_get_health |
Check Radarr health status and warnings |
radarr_get_disk_space |
List disk space on drives containing movies |
Prowlarr (14 tools)
| Tool | Purpose |
|---|---|
prowlarr_search |
Search configured indexers for releases |
prowlarr_grab_release |
Send a release to the download client (bypasses Sonarr/Radarr tracking) |
prowlarr_list_indexers |
List configured indexers with protocol and status |
prowlarr_get_indexer |
Get details about a specific indexer |
prowlarr_test_indexer |
Test connectivity of an indexer |
prowlarr_get_indexer_stats |
Get query and grab statistics for each indexer |
prowlarr_get_indexer_status |
Get health and backoff status of indexers |
prowlarr_list_categories |
List newznab categories supported by indexers |
prowlarr_get_history |
Get history of indexer queries and grabs |
prowlarr_list_applications |
List *arr applications synced by Prowlarr |
prowlarr_list_download_clients |
List download clients configured in Prowlarr |
prowlarr_run_command |
Run administrative commands (sync, health check) |
prowlarr_get_system_status |
Get Prowlarr version and system information |
prowlarr_get_health |
Get health check results for Prowlarr |
Overseerr (28 tools)
| Tool | Purpose |
|---|---|
overseerr_search |
Search Overseerr for movies, TV shows, and people by title |
overseerr_discover_movies |
Discover popular and upcoming movies from TMDB |
overseerr_discover_tv |
Discover popular and upcoming TV shows from TMDB |
overseerr_get_trending |
List currently trending movies and TV shows |
overseerr_get_movie |
Get full Overseerr/TMDB details for one movie |
overseerr_get_tv |
Get full Overseerr/TMDB details for one TV series |
overseerr_get_movie_recommendations |
Get movies recommended based on a given movie |
overseerr_get_similar_movies |
Get movies similar to a given movie |
overseerr_get_tv_recommendations |
Get TV shows recommended based on a given show |
overseerr_get_similar_tv |
Get TV shows similar to a given show |
overseerr_get_movie_ratings |
Get Rotten Tomatoes and IMDB ratings for a movie |
overseerr_get_tv_ratings |
Get Rotten Tomatoes ratings for a TV show |
overseerr_get_person |
Get biography and details for a person |
overseerr_get_person_credits |
Get a person’s combined movie and TV credits |
overseerr_list_requests |
List media requests with optional filtering and sorting |
overseerr_get_request |
Get one media request by id |
overseerr_get_request_count |
Get counts of requests by status |
overseerr_create_request |
Request that a movie or TV show be added |
overseerr_update_request_status |
Approve or decline a pending media request |
overseerr_retry_request |
Retry a failed request to Sonarr or Radarr |
overseerr_delete_request |
Destructive: Permanently remove a media request |
overseerr_list_media |
List media items known to Overseerr with their availability status |
overseerr_delete_media |
Destructive: Remove a media item from Overseerr |
overseerr_list_users |
List Overseerr users |
overseerr_get_system_status |
Get Overseerr version and update status |
overseerr_list_radarr_servers |
List the Radarr servers Overseerr routes to, with each one’s default root folder |
overseerr_get_radarr_profiles |
List quality profiles available on one of those Radarr servers |
overseerr_update_request |
Change a request’s root folder, quality profile or target server |
Organising a library
Several tools exist to audit and correct how a library is filed on disk.
radarr_list_movies and sonarr_list_series filter by rootFolder, genre, titleContains and monitored/file state, and return genres and originalLanguage in the summary. That makes it possible to answer questions like “which animation-genre films are filed under the live-action root” in a single call, instead of one lookup per title. rootFolder matches whole path segments: /media/movies selects that folder only, not /media/movies-animation or /media/movies-anime.
To correct what you find, radarr_update_movie and sonarr_update_series accept a rootFolderPath, and radarr_bulk_edit_movies / sonarr_bulk_edit_series do the same for many items at once. Pass moveFiles: true to relocate the files on disk rather than only changing the record.
Radarr and Sonarr move the files before the bulk editor returns, and a large batch can outlast the MCP client’s request timeout. So the two bulk editors accept at most 10 ids per call when moveFiles is true, and reject a larger batch with an error before anything is sent. Send bigger sets as sequential batches of 10 or fewer, one call at a time. Batches that only change metadata (monitored state, quality profile, tags) are not limited.
radarr_list_unmapped_folders and sonarr_list_unmapped_folders show folders present on disk that the application has no entry for; radarr_import_folder and sonarr_import_folder scan such a folder and import what they find. radarr_get_rename_preview and sonarr_get_rename_preview show the names a rename would produce before you run one, and the find_duplicate_* tools report titles present under more than one root folder.
Routing is decided upstream: overseerr_list_radarr_servers reports the activeDirectory each Radarr server defaults to, which is usually what determines where new requests land. Note that overseerr_update_request changes where a request will be sent — it does not move media that has already been downloaded. Use the Radarr or Sonarr tools for that.
Safety note: deleting files through radarr_delete_movie or sonarr_delete_series requires confirmDeleteFiles: true. Called without it, these tools return a description of what would be lost and delete nothing. The bulk editors deliberately do not expose file deletion at all.
Finding Your API Key
In each application’s web UI:
- Go to Settings
- Click General
- Scroll to the API Key field
- Copy the entire string
This is a sensitive credential — treat it like a password. Do not commit it to version control or share it.
Development
Prerequisites
- Node.js 20 or later
- npm 10+
Running Tests
npm test
Linting and Type Checking
npm run lint
npm run typecheck
Building
npm run build
This emits compiled JavaScript to dist/index.js.
Running Locally
First build the project, then run it:
npm run build
Then start the server with your configuration:
# Set up environment variables
export SONARR_URL=http://localhost:8989
export SONARR_API_KEY=your-key
# ... other env vars
node dist/index.js
Install
docker run --rm -i --add-host=host.docker.internal:host-gateway --env SERVARR_MCP_TRANSPORT=stdio --env SONARR_URL=http://host.docker.internal:8989 --env SONARR_API_KEY=your-sonarr-api-key --env RADARR_URL=http://host.docker.internal:7878 --env RADARR_API_KEY=your-radarr-api-key --env PROWLARR_URL=http://host.docker.internal:9696 --env PROWLARR_API_KEY=your-prowlarr-api-key --env OVERSEERR_URL=http://host.docker.internal:5055 --env OVERSEERR_API_KEY=your-overseerr-api-key ghcr.io/jfms7s/servarr-mcp:latestConfiguration
{
"mcpServers": {
"servarr": {
"command": "node",
"args": ["/path/to/servarr-mcp/dist/index.js"],
"env": {
"SONARR_URL": "http://localhost:8989",
"SONARR_API_KEY": "your-sonarr-api-key",
"RADARR_URL": "http://localhost:7878",
"RADARR_API_KEY": "your-radarr-api-key",
"PROWLARR_URL": "http://localhost:9696",
"PROWLARR_API_KEY": "your-prowlarr-api-key",
"OVERSEERR_URL": "http://localhost:5055",
"OVERSEERR_API_KEY": "your-overseerr-api-key"
}
}
}
}