reclaimerr-mcp-server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@reclaimerr-mcp-serverShow me media flagged for deletion in my Jellyfin library."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
reclaimerr-mcp-server
A minimal Model Context Protocol server that connects to Reclaimerr (automated media-library cleanup — reclaims disk space by identifying unwatched/low-rated media across Jellyfin/Plex/Emby and managing deletion through Sonarr/Radarr), packaged for Docker.
It runs as a standing network service (streamable-http transport, not stdio),
so any MCP client on your internal network can connect to
http://<host>:<port>/mcp — the container isn't spawned per-client, and
container lifecycle/updates can be handed off to a tool like
Dockhand.
API assumptions
Reclaimerr ships a real, versioned external API at a fixed /api/v1 prefix
(FastAPI backend, source: backend/api/routes/v1/),
authenticated with scoped Bearer API tokens (rcl_<prefix>_<secret>, created
in its own UI). This server was built directly against that source (repo at
jessielw/Reclaimerr, backend
version 0.4.7 at the time of writing) since Reclaimerr's docs site doesn't
publish full endpoint-level API reference — it has not been exercised
against a live instance yet. Run GET /ready (see below) after configuring
RECLAIMERR_URL/RECLAIMERR_API_TOKEN and, ideally, run the opt-in live
contract tests (tests/test_live_reclaimerr.py) once before relying on this
in anything important — a point release could have renamed a field these
tools depend on.
Unlike Sonarr/Radarr/Prowlarr, there's no server-reported API version to
negotiate (no RECLAIMERR_API_VERSION env var here) — Reclaimerr's /api/v1
prefix is fixed, and GET /api/v1 itself reports api_version informationally.
Related MCP server: OpenRefine MCP Server
Tools
Tool | Description | Required scope |
| List reclaim candidates (media flagged for possible deletion), optionally filtered by media type or auto-delete state |
|
| Full lifecycle detail for one candidate by ID |
|
| Permanently protect a candidate from deletion |
|
| Push a candidate's deletion deadline to a later timestamp |
|
| Cancel a pending scheduled deletion |
|
| List protected (deletion-exempt) media |
|
| List background tasks (media sync, candidate scan, cleanup, ...) with schedule/status |
|
| Trigger an immediate run of a background task |
|
| Reclaimerr version, capabilities, last sync/scan times |
|
protect_candidate, postpone_candidate, cancel_candidate_deletion, and
run_task are the tools that change state in Reclaimerr. Everything else is
read-only. Scope your RECLAIMERR_API_TOKEN down to just the tools you want
an MCP client to be able to call — e.g. a read-only token (no :manage or
:run scopes) if you only want visibility, not control.
Health endpoints
Two plain HTTP endpoints, reachable without MCP_AUTH_TOKEN (so Docker's
HEALTHCHECK, Dockhand, or any other monitor can poll them without the
secret):
Endpoint | Checks | Healthy | Unhealthy |
| The process is up and serving HTTP. Does not call Reclaimerr. |
| (doesn't respond) |
|
|
|
|
/ready distinguishes a 401 (bad/revoked token) from a 403 (valid token,
missing the system:read scope) in its error message — useful when a token
was created with the wrong scopes.
Authentication
Set MCP_AUTH_TOKEN (a random shared secret — openssl rand -hex 32) and
every request must carry Authorization: Bearer <token> or the server
returns 401. This is checked by a small Starlette middleware in front of
the MCP app, not the mcp SDK's built-in OAuth support
(mcp.server.auth) — that machinery expects a full OAuth authorization
server (issuer/resource metadata, RFC 8414/8707/9068 discovery), which is
unnecessary complexity for one secret shared by trusted LAN clients. This is
a separate secret from RECLAIMERR_API_TOKEN — the latter authenticates
this server to Reclaimerr, the former authenticates MCP clients to this
server.
Leave MCP_AUTH_TOKEN unset and the server runs with no auth — anything
that can reach http://<host>:<port>/mcp can call every tool, including the
state-changing ones. The server logs a warning on startup when it's running
this way. Either way, the trust boundary is still the network:
Do not publish this port through any reverse proxy, port-forward, or anything else reachable from outside your LAN/VLAN — the bearer token protects against anyone on the network, not against the open internet.
Bind the compose
ports:mapping to a specific internal interface (e.g.192.168.1.50:8941:8941) rather than all interfaces, if you want to be stricter about which hosts on your network can reach it at all.
Configuration
Environment variables (see .env.example):
Variable | Required | Default | Description |
| yes | — | e.g. |
| yes | — | Reclaimerr > Settings > Account > API Tokens ( |
| no |
| Interface the server binds to inside the container |
| no |
| Port the server listens on |
| no | — | Shared secret required as |
Image
Built and pushed to ghcr.io/barrow1990/reclaimerr-mcp-server by
.github/workflows/ci.yml on every push to
main that passes tests, tagged :latest and :<commit-sha>.
docker-compose.yml pulls :latest by default; swap in build: . there
instead if you'd rather build locally from the Dockerfile.
The image is a three-stage build: builder compiles dependencies into
--target=/deps (all of them, including cryptography's compiled cffi
extension, ship musllinux wheels, so this needs no compiler even on alpine);
prep starts fresh from python:3.12-alpine, drops pip/setuptools/wheel,
strips stdlib pieces this headless server never touches (tkinter,
idlelib, lib2to3, ensurepip, ...), adds the non-root app user, and
copies in /deps and server.py; runtime then does a single
COPY --from=prep / / onto a scratch base — the same build shape used by
the sonarr-mcp-server/radarr-mcp-server images this one was adapted from,
landing at roughly the same ~98MB.
Running with Docker Compose
cp .env.example .env # fill in RECLAIMERR_URL / RECLAIMERR_API_TOKEN
docker compose up -d --pull alwaysThe server is then reachable at http://<docker-host>:8941/mcp from anything
on your internal network.
Managing with Dockhand
Point Dockhand at ghcr.io/barrow1990/reclaimerr-mcp-server and let it track
new tags. Make the GHCR package public, or every pull will need docker login ghcr.io with a PAT on each deploy host. Set a restart policy of
unless-stopped (already in docker-compose.yml). See the sonarr-mcp-server/
radarr-mcp-server READMEs for the fuller rundown of .env/.env.dockhand
precedence — this repo follows the same pattern.
Connecting a client
Claude Code
claude mcp add reclaimerr -s user --transport http http://<docker-host>:8941/mcp \
--header "Authorization: Bearer <MCP_AUTH_TOKEN>"(Drop the --header flag if you're running with MCP_AUTH_TOKEN unset.)
Claude Desktop
Claude Desktop's built-in config expects a locally-spawned command, so for
a network server like this you'll need an HTTP-to-stdio bridge such as
mcp-remote:
{
"mcpServers": {
"reclaimerr": {
"command": "npx",
"args": [
"-y", "mcp-remote", "http://<docker-host>:8941/mcp",
"--header", "Authorization: Bearer <MCP_AUTH_TOKEN>"
]
}
}
}Running without Docker
pip install -r requirements.txt
RECLAIMERR_URL=http://192.168.1.50:8000 RECLAIMERR_API_TOKEN=rcl_your_token \
MCP_AUTH_TOKEN=your-shared-secret python server.pyTesting
pip install -r requirements-dev.txt
python -m pytest tests/ -vtests/test_tools.py— each tool's logic against a mocked Reclaimerr (httpx.MockTransport, no extra mocking library needed).tests/test_http.py—/health,/ready, and the bearer-auth middleware, viaserver.build_app()(the exact app__main__runs) through Starlette'sTestClient.tests/test_live_reclaimerr.py— opt-in contract tests against a real Reclaimerr instance, to catch drift if an upgrade renames/removes a field these tools depend on. Skipped by default (no Reclaimerr in CI); run with:RUN_LIVE_RECLAIMERR_TESTS=1 RECLAIMERR_URL=https://reclaimerr.example.com \ RECLAIMERR_API_TOKEN=<real rcl_... token> python -m pytest tests/test_live_reclaimerr.py -v
CI (.github/workflows/ci.yml) runs the mocked suite on every push/PR; the
GHCR build only runs after it passes.
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Wikimedia Commons MCP — Action API for files.
Query, browse, and automate OmegaAI workspaces from any MCP client. Streamable HTTP with OAuth 2.0.
Search and retrieve published Alkemata articles, pages, and guidance through a read-only MCP server.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables MCP-compatible clients to interact with an Immich photo management instance, providing access to users, assets, API keys, and partners through standardized resources and tools.1MIT
- AlicenseAqualityDmaintenanceEnables MCP-capable clients to interact with OpenRefine's HTTP API for creating projects, applying operations, exporting CSV, and deleting projects.410MIT
- AlicenseNot gradedqualityCmaintenanceExposes BookClaw's author workflow to MCP clients over Streamable HTTP, providing tools for managing books, projects, pipelines, and more.MIT
- AlicenseNot gradedqualityBmaintenanceExposes a running Tentyl mesh (messaging, DMs, reactions, search, presence, etc.) as MCP tools via a thin REST client.MIT