Self-Hosted Media Stack, Part 8: Give Claude Real Access to Your Library
Part 8 of Media Stack from Scratch. Everything here assumes Sonarr and Radarr from Part 2 are up and you've still got their API keys noted down.
Seven parts built a stack that runs itself. This part gives an AI assistant a way to talk to it — "what's downloading right now," "add this show," "why hasn't episode 4 imported yet" — answered in plain language instead of you opening Sonarr's UI and hunting through the queue. The mechanism is MCP (Model Context Protocol): a small standard that lets an AI client like Claude connect to a server exposing a set of "tools" — in this case, Sonarr and Radarr's own REST APIs, wrapped so an AI can call them directly.
Summary
- You already have everything this needs: Sonarr and Radarr's API keys from Part 2.
- One ready-made MCP server (
mcp-arr-server) speaks Sonarr and Radarr's API — no custom code, one config block. claude mcp listshowing "✔ Connected" is not proof the tools loaded — a missing or empty API key still shows a green check. This is the trap that costs the most time.- A new MCP server needs Claude itself restarted, not just reconfigured.
- The API key this uses is all-or-nothing — full read/write, no read-only mode. Treat it like any other credential: it stays off the public internet.
What MCP actually is, in one paragraph
An MCP server is a small program that exposes a fixed set of tools — named
actions with typed inputs — that an AI client can call. Point Claude at one, and it
can call get_series, add_movie, get_queue, or whatever that server defines,
the same way it can read a file or run a search. The server does the actual HTTP call
to Sonarr/Radarr; Claude just decides when to call which tool based on what you
asked in plain language.
You don't write this server yourself for something as common as Sonarr/Radarr — one already exists.
Wiring up mcp-arr-server
This is the exact config block for both Sonarr and Radarr at once — one MCP server, both apps, using the API keys you already noted in Part 2 (Settings → General → API Key in each app):
{
"mcpServers": {
"arr": {
"command": "npx",
"args": ["-y", "mcp-arr-server"],
"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"
}
}
}
}
Where this block goes depends on which Claude you're using:
- Claude Desktop:
claude_desktop_config.json(Settings → Developer → Edit Config opens it directly). - Claude Code:
.mcp.jsonin your project root, orclaude mcp addfrom the CLI if you'd rather not hand-edit JSON.
npx -y mcp-arr-server means Claude launches the server itself, on demand, the first
time it's needed — no container to run, no port to publish. If Sonarr/Radarr are
themselves behind Tailscale rather than on
localhost, point the URLs at their tailnet addresses instead.
The trap: a green checkmark that lies
This is worth stating plainly because it's the single most time-wasting failure mode:
claude mcp list reporting a server as "✔ Connected" only proves the process
started — it says nothing about whether the tools inside it actually work. An empty
or wrong API key doesn't stop the server from launching; it just makes every tool call
fail once Claude actually tries to use one, with no earlier warning.
If Claude reports it has no arr-related tools available, or every request errors, don't trust the green check — go straight to the actual API keys and confirm they're current in both the config and in Sonarr/Radarr's own settings.
The trap: reconfiguring isn't enough — restart Claude itself
Editing the MCP config while Claude is already running doesn't do anything on its own. The client's connection to each MCP server is established once, at startup — adding a new server, or fixing a broken one, needs Claude Desktop or Claude Code restarted, not just the config file resaved. This one's easy to miss because nothing errors — Claude just keeps behaving as if the new server doesn't exist, for as long as you keep the same session open.
The trap: this API key is all-or-nothing
Sonarr and Radarr's API keys don't have a read-only mode — the key that lets Claude look up what's downloading is the exact same key that lets it delete a series or change your quality profiles. That's not a flaw specific to MCP; it's just how these apps' APIs have always worked, and it's worth being deliberate about now that something else is calling it on your behalf:
- Keep it off the public internet the same way you would any other credential — Tailscale-only is the right default for anything this capable, never a public Cloudflare route.
- If you ever need to hand access to more than one device or person, a shared, centrally-managed MCP endpoint (bearer-auth in front of it, one gateway aggregating several backends) is the natural next step up from per-device local config — a genuinely more advanced setup, and a fair "Part 9" if there's appetite for it, not something to reach for on day one.
What this actually looks like in use
With the config above and Claude restarted, you can ask things like:
- "What's currently downloading?" — Claude calls the queue endpoint on both apps and summarizes it.
- "Add [show] to Sonarr, 1080p profile" — a real add, using the profile you set up in Part 2.
- "Why is [episode] stuck?" — Claude can check the queue and recent history and give you an actual answer instead of you clicking through Sonarr's UI to find it.
None of this replaces the stack from Parts 1–7 — it's a different way of talking to the same thing that was already running.
Checkpoint
mcp-arr-serverconfigured with both apps' real API keys and URLs- Claude restarted after adding it (not just the config file saved)
- Confirmed actual tool calls work — not just a green "Connected" status
- The key treated like any other credential: no public exposure
Previous: Part 7 — Profilarr. Start of the series: Part 1 — the map.
If this saved you some time, a coffee keeps the lights on and the posts coming.
☕ Buy me a coffee