mcpField
S
seerr-mcp-server

seerr-mcp-server

Local
github.com/cyanheadsGames & Entertainment3Updated 3w ago

About seerr-mcp-server

seerr-mcp-server supports workflows for Jellyseerr and Overseerr users by searching media, confirming matches, checking availability, and creating requests. Writes default to preview and require confirmation; Jellyseerr handles request permissions and routing, while the server does not call Radarr or Sonarr directly.

Key features

  1. 01Search movies and TV titles
  2. 02Check media details, availability, and requests
  3. 03Filter and list recent requests
  4. 04Preview and confirm media requests
  5. 05Inspect request status and routing
  6. 06Review Radarr/Sonarr service options

Use cases

  1. 01Confirm a title match before requesting it
  2. 02Check existing requests to avoid duplicates
  3. 03Review request progress and media availability
  4. 04Inspect configured services and quality profiles

MCP support

Exposes 6 tools and 1 request resource to MCP clients over STDIO or Streamable HTTP.

Configuration

Local server config is the same for every client. Copy it into your client’s MCP config file.

mcp.json · Universal config
{
"mcpServers": {
"cyanheads-seerr": {
"command": "npx",
"args": [
"-y",
"@cyanheads/seerr-mcp-server"
],
"env": {
"SEERR_BASE_URL": "<SEERR_BASE_URL>",
"SEERR_API_KEY": "<SEERR_API_KEY>",
"SEERR_REQUEST_TIMEOUT_MS": "<SEERR_REQUEST_TIMEOUT_MS>",
"MCP_LOG_LEVEL": "<MCP_LOG_LEVEL>",
"MCP_TRANSPORT_TYPE": "<MCP_TRANSPORT_TYPE>",
"MCP_HTTP_HOST": "<MCP_HTTP_HOST>",
"MCP_HTTP_PORT": "<MCP_HTTP_PORT>",
"MCP_HTTP_ENDPOINT_PATH": "<MCP_HTTP_ENDPOINT_PATH>",
"MCP_AUTH_MODE": "<MCP_AUTH_MODE>"
}
}
}
}
Run commandnpx -y @cyanheads/seerr-mcp-server
Environment variables to set
SEERR_BASE_URLBase URL of the Jellyseerr/Overseerr instance, e.g. http://host:5055. No /api/v1 suffix, no trailing slash.
SEERR_API_KEYSecretSeerr API key (Settings → General → API Key), sent as the X-Api-Key header.
SEERR_REQUEST_TIMEOUT_MSPer-request HTTP timeout in milliseconds.
MCP_LOG_LEVELSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
MCP_TRANSPORT_TYPESelects the HTTP transport.
MCP_HTTP_HOSTThe hostname for the HTTP server.
MCP_HTTP_PORTThe port to run the HTTP server on.
MCP_HTTP_ENDPOINT_PATHThe endpoint path for the MCP server.
MCP_AUTH_MODESecretAuthentication mode to use: 'none', 'jwt', or 'oauth'.

Local servers need a runtime on your machine (e.g. Node.js 18+). Config file locations differ by client; see your client’s docs.

Packages
npm@cyanheads/seerr-mcp-server0.1.5

Tools

6

Saved tool list · updated 2w ago

ParameterTypeRequiredDescription
pageintegerNo1-based result page. Seerr returns ~20 results per page; use with a prior call to page through.
limitintegerNoMax normalized results to return from this page (caps output size; does not change which page is fetched).
querystringYesTitle to search for, e.g. "Mulan" or "Severance". Natural-language titles are fine; Seerr matches against TMDB.
languagestringNoISO 639-1 language for titles/overviews, e.g. "en" or "pt-BR". Defaults to the Seerr instance locale when omitted.
mediaTypeenumNoRestrict results to movies, TV shows, or both. People are always excluded — this server requests media, not actors.movie | tv | all

Details

From the project README

@cyanheads/seerr-mcp-server

Search Jellyseerr/Overseerr, check availability, and create guarded media requests via MCP. STDIO or Streamable HTTP.

6 Tools • 1 Resource

Version License MCP SDK npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework


Overview

Jellyseerr and Overseerr media-request workflow: search TMDB-backed titles, confirm the exact match, check availability and request state, and create a guarded request that Radarr/Sonarr act on. Jellyseerr owns permissions, quotas, routing, and status — this server never calls Radarr/Sonarr directly. Runs as a stdio process or a local Streamable HTTP server.

Tools
ToolDescription
seerr_search_mediaSearch movies and TV by title; returns ranked matches with TMDB ID, year, overview, and decoded availability when Jellyseerr already tracks the title. The required first step before requesting.
seerr_get_mediaFetch exact movie/show details by TMDB ID + media type to confirm the title before a write; for TV, a per-season summary or one season's episode list.
seerr_list_requestsList recent requests with status/type/requester filters; echoes the applied filters and decodes every numeric status. Titles are opt-in via includeTitles.
seerr_request_mediaGuarded write. Previews the request payload by default (mode: preview); creates the request only on mode: request, and only after an accepted confirmation.
seerr_request_statusFetch one request by ID — title, decoded request + media availability (incl. 4K), requester, routing summary, and a state-tuned next-step hint.
seerr_service_optionsSummarize configured Radarr/Sonarr services, default quality profiles, and instance capability flags (4K, partial requests, specials, media server). Filesystem paths redacted unless includePaths.
Resources
ResourceDescription
seerr://request/{requestId}Read-once summary of one request — decoded status, media availability, requester, and routing. Mirrors seerr_request_status.

All request data is also reachable via tools — request enumeration is the job of seerr_list_requests (the tool-only access path).

Capability reference

seerr_search_media tool
  • Search titles with mediaType: movie | tv | all; people are excluded. page is 1–1000; limit is 1–20, default 10.
  • Returns TMDB matches and decoded status / status4k for tracked titles. Empty results return [] with a guidance notice.
  • Optional ISO 639-1 language selects localized titles and overviews.

seerr_get_media tool
  • Availability plus any existing open request for the title (avoids duplicate requests)
  • TV: omit seasonNumber for a per-season summary, or pass one to fetch that season's episode list (season 0 is Specials)
  • A TMDB ID that doesn't resolve surfaces as a typed media_not_found with a search-recovery hint (Jellyseerr's raw HTTP 500 is classified in the service layer)

seerr_list_requests tool
  • Filter by lifecycle filter, mediaType, and requestedById; sort by added or modified, ascending or descending. take is 1–100, default 20; skip selects the offset.
  • Returns decoded statuses, requester { id, displayName }, and an enrichment trailer with applied filters.
  • includeTitles: true joins media titles once per distinct title (default off); unresolved rows retain their data and are disclosed in the notice.

seerr_request_media tool
  • Guarded write. mode: preview (default) returns the resolved title and exact POST /request payload without writing. mode: request asks for confirmation bound to the same caller, title and payload; declined, cancelled or invalid answers return request_cancelled.
  • TV requests require seasons: "all" or a list such as [1, 2]; season 0 (Specials) requires special episodes to be enabled. Instance capability checks run before any POST; existing requests appear in output and duplicate rejections return duplicate_request.
  • Optional routing overrides: serverId, profileId, rootFolder, languageProfileId. Omit them to use Jellyseerr's defaults.

seerr_request_status tool
  • Accepts requestId from seerr_request_media's created.requestId or seerr_list_requests. A missing request returns request_not_found.
  • Returns decoded requestStatus, mediaStatus / mediaStatus4k, requester { id, displayName }, routing (serverId, profileName, is4k), and stateGuidance.
  • Joins title on each call; it is absent when no tmdbId exists or the lookup fails.

seerr_service_options tool
  • Returns instance version, media server, capability flags (movie4kEnabled, series4kEnabled, partialRequestsEnabled, specialEpisodesEnabled), and service IDs, defaults and quality profiles.
  • Failed service legs retain the available results with a notice.
  • includePaths: true exposes root-folder paths and free space; both are omitted by default.

seerr://request/{requestId} resource
  • Accepts requestId from seerr_request_media or seerr_list_requests; a missing request returns request_not_found.
  • Mirrors seerr_request_status, including redaction and a title join. title is absent when no tmdbId exists or the lookup fails; resources take no per-read options.

Features

Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.

HTTP requires stateful sessions for 2025-era confirmation rounds; explicit MCP_SESSION_MODE=stateless fails startup. Consent records expire after ten minutes and changed or replayed records ask again. Redemption excludes concurrent retries in one process; request creation makes one POST attempt without automatic retries. Cross-instance read-and-delete is not atomic: use shared strongly consistent filesystem, Supabase or Cloudflare D1 storage for routed retries, and account for duplicate-submission races; Cloudflare KV is unsuitable for consent records.

Seerr-specific:

  • Read + guarded-request only — admin-scope endpoints (approve/decline, retry, edit/delete, media/file deletion, user/settings/sync) are excluded by design, not by API limitation
  • PII/infra redaction centralized in one normalizer choke point — requesters project to { id, displayName }; operator email, Plex/Jellyfin tokens, and serviceUrl never reach output; filesystem paths are opt-in via includePaths
  • Status decoding centralized in one helper — request and media statuses (including the separate 4K availability) decode to { raw, label } everywhere, forward-compatible with new Jellyseerr status codes
  • Capability validation against cached instance settings catches most bad requests before they reach the API
  • A short-TTL settings cache avoids a round-trip on every preview

Agent-friendly output:

  • Provenance and disclosure — searches echo the effective query; capped lists disclose truncation; a degraded service leg surfaces a notice instead of silently dropping data
  • Typed, actionable errors — media_not_found, request_not_found, seasons_required, four_k_not_enabled, duplicate_request, and more carry a recovery hint so callers can branch and retry without parsing prose

Getting started

Add the following to your MCP client configuration file, pointing SEERR_BASE_URL at your own Jellyseerr or Overseerr instance and supplying its API key.

{
  "mcpServers": {
    "seerr-mcp-server": {
      "type": "stdio",
      "command": "bunx",
      "args": ["@cyanheads/seerr-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info",
        "SEERR_BASE_URL": "http://localhost:5055",
        "SEERR_API_KEY": "your-api-key"
      }
    }
  }
}

Or with npx (no Bun required):

{
  "mcpServers": {
    "seerr-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cyanheads/seerr-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info",
        "SEERR_BASE_URL": "http://localhost:5055",
        "SEERR_API_KEY": "your-api-key"
      }
    }
  }
}

For Streamable HTTP, set the transport and start the server:

MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 SEERR_BASE_URL=http://localhost:5055 SEERR_API_KEY=your-api-key bun run start:http
# Server listens at http://localhost:3010/mcp
Prerequisites
  • Bun v1.4.0 or higher (or Node.js v24+).
  • A running Jellyseerr or Overseerr instance, and its API key (Settings → General → API Key).
Installation
  1. Clone the repository:
git clone https://github.com/cyanheads/seerr-mcp-server.git
  1. Navigate into the directory:
cd seerr-mcp-server
  1. Install dependencies:
bun install
  1. Configure environment:
cp .env.example .env
# edit .env — set SEERR_BASE_URL and SEERR_API_KEY

Configuration

All configuration is validated at startup via Zod schemas in src/config/server-config.ts. Key environment variables:

VariableDescriptionDefault
SEERR_BASE_URLRequired. Base URL of the Jellyseerr/Overseerr instance, e.g. http://localhost:5055. The service appends /api/v1 — no /api/v1 suffix, no trailing slash.—
SEERR_API_KEYRequired. Jellyseerr API key (Settings → General → API Key). Sent as the X-Api-Key header.—
SEERR_REQUEST_TIMEOUT_MSPer-request HTTP timeout in milliseconds.15000
MCP_TRANSPORT_TYPETransport: stdio or http.stdio
MCP_HTTP_PORTPort for the HTTP server.3010
MCP_AUTH_MODEAuth mode: none, jwt, or oauth.none
MCP_LOG_LEVELLog level (RFC 5424).info
LOGS_DIRDirectory for log files (Node.js only).<project-root>/logs
STORAGE_PROVIDER_TYPEStorage backend.in-memory
MCP_SESSION_MODEHTTP session mode; must resolve to stateful for confirmation rounds. The example and Docker image set stateful; an unset value uses auto, resolving to stateful. Explicit stateless fails startup.auto
MCP_REQUEST_STATE_KEYOptional key of at least 32 bytes, shared across instances, that seals consent record IDs.—
OTEL_ENABLEDEnable OpenTelemetry instrumentation.false
OTEL_EXPORTER_OTLP_ENDPOINTOTLP base for traces and metrics; signal-specific endpoints override it.—
OTEL_EXPORTER_OTLP_LOGS_ENDPOINTOpt-in log export endpoint; the base endpoint never enables logs.—
LOG_TOOL_FAILURE_PAYLOADSOpt-in failed-call arguments/result logging; redaction matches key names, so secrets in free-form values can remain.false

See .env.example for the full list of optional overrides.

Running the server

Local development
  • Build and run:

    # One-time build
    bun run rebuild
    
    # Run the built server
    bun run start:stdio
    # or
    bun run start:http
    
  • Run checks and tests:

    bun run devcheck   # Lint, format, typecheck, security, changelog sync
    bun run test       # Vitest test suite
    bun run lint:mcp   # Validate MCP definitions against spec
    
Docker
docker build -t seerr-mcp-server .
docker run --rm \
  -e SEERR_BASE_URL=http://host.docker.internal:5055 \
  -e SEERR_API_KEY=your-api-key \
  -p 3010:3010 \
  seerr-mcp-server

The Dockerfile defaults to HTTP transport, stateful session mode, and logs to /var/log/seerr-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.

Project structure

DirectoryPurpose
src/index.tscreateApp() entry point — registers the six tools + one resource and inits the Seerr service.
src/configServer-specific environment variable parsing and validation with Zod.
src/mcp-server/toolsTool definitions (*.tool.ts).
src/mcp-server/resourcesResource definitions (*.resource.ts).
src/services/seerrJellyseerr API client, status decoders, and the PII/infra redaction normalizers.
tests/Unit and integration tests mirroring src/.

Development guide

See CLAUDE.md/AGENTS.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic
  • Use ctx.log for request-scoped logging, ctx.state for tenant-scoped storage
  • Register new tools and resources via the barrels in src/mcp-server/*/definitions/index.ts
  • Wrap the Jellyseerr API: validate raw → normalize and redact to a domain type → return the output schema; never fabricate missing fields, and never let operator PII or paths reach output

Contributing

Issues are welcome. Run checks and tests before submitting:

bun run devcheck
bun run test

License

Apache-2.0 — see LICENSE for details.

Comments

Markdown supported

New to MCP?

From what the protocol is to installing your first server, these answers cover most first questions.

An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.