leachuk/listenarr-mcp

1

stars

1

commits

Go

primary language

Aug 19, 2026

updated

README

listenarr-mcp

A Model Context Protocol server for Listenarr, the automated audiobook collection manager. It lets an AI assistant browse your library, search the Audible catalogue, grab releases from your indexers, and diagnose downloads that got stuck — through Listenarr's own REST API.

Built in Go, following the architecture of jellyfin-mcp.

Note. There is a dependency on a local docker registry if you're deploying this to a local k8s node. You'll need to change this for your own k8s setup. See https://github.com/leachuk/listenarr-mcp/blob/main/k8s/plain/deployment.yaml

What it can do

15 tools across 7 toolsets:

ToolsetToolsWhat it covers
librarylistenarr_library, listenarr_library_add, listenarr_library_edit, listenarr_library_deleteBrowse and filter the collection, add books by ASIN, edit monitoring and metadata, rename/move files, delete entries
searchlistenarr_search, listenarr_metadataAudible catalogue lookups (with fuzzy ranking), indexer release searches, author and series catalogues
downloadslistenarr_downloads, listenarr_download_grab, listenarr_download_manageWatch transfers, grab releases, retry blocked imports, cancel and purge
monitoringlistenarr_monitoringStanding subscriptions to an author or a series
indexerslistenarr_indexersInspect, test, toggle, and remove indexers
configlistenarr_configRoot folders, quality profiles, download clients, settings (credentials masked)
systemlistenarr_system, listenarr_historyConnectivity, health, storage, logs, and the activity audit trail

Plus 13 resources (library, wanted list, active downloads, queue, health, root folders, indexers, recent history, per-book detail, and four reference guides) and 6 prompts for guided workflows: find-and-add, whats-downloading, finish-series, library-health, follow-author, and diagnose-stuck-download.

The one distinction that matters

Three things all look like "search", and they are not interchangeable:

listenarr_library      action=list          → what you ALREADY HAVE
listenarr_search       action=metadata      → the Audible CATALOGUE  → yields an ASIN
listenarr_search       action=indexers      → downloadable RELEASES  → yields a download_reference

The server's instructions spell this out to the model, because getting it wrong is the most common way an assistant wastes calls on this kind of API.

Configuration

VariableRequiredDefaultNotes
LISTENARR_API_KEYyesListenarr → Settings → General
LISTENARR_URLnohttp://listenarr:4545In-cluster Service DNS name when running in Kubernetes
LISTENARR_API_VERSIONnov1URL segment; only change if Listenarr ships a v2
LISTENARR_TIMEOUT_SECONDSno60Raise if indexer searches time out

The server authenticates to Listenarr with the X-Api-Key header.

Flags

--toolsets library,search,system   register only these tool groups
--read-only                        register only tools that cannot change anything
--disable-destructive              allow writes, but no deletes or cancellations
--http                             serve streamable HTTP instead of stdio
--addr 0.0.0.0:8080                HTTP listen address
--http-token <secret>              bearer token; REQUIRED for non-localhost binds

--read-only and --disable-destructive are enforced at registration time: a tool that is never registered cannot be called, whatever the model attempts.

Running it

Locally, over stdio

cp .env.example .env && $EDITOR .env
make run

Or point an MCP client at the binary:

{
  "mcpServers": {
    "listenarr": {
      "command": "/path/to/listenarr-mcp",
      "env": {
        "LISTENARR_URL": "http://192.168.0.129:30545",
        "LISTENARR_API_KEY": "your-api-key"
      }
    }
  }
}

On Kubernetes (this cluster)

MCP servers here run under ToolHive in the mcp namespace, alongside mcp-jellyfin and mcp-arr. ToolHive runs the container over stdio and fronts it with its own streamable-HTTP proxy.

# 1. Build and publish the image to the local registry
make docker-build docker-push

# 2. Create the API key secret
make k8s-secret

# 3. Create the MCPServer (and optional NodePort on 30802)
make k8s-apply

# 4. Check it came up
make k8s-status

The endpoint is then:

http://mcp-mcp-listenarr-proxy.mcp.svc.cluster.local:8080/mcp

Manifests live in k8s/. See k8s/README.md for the details, including a plain-Kubernetes alternative in k8s/plain/ for running without ToolHive.

Publishing to the local registry

make docker-push uses skopeo, not docker push. Two reasons, both specific to this setup:

  • the registry at 192.168.0.129:30050 serves plain HTTP, and Docker refuses that without an insecure-registries entry;
  • Docker Desktop's Linux VM cannot route to that LAN address at all, while the Mac itself can.

skopeo runs natively on the host and --dest-tls-verify=false handles the HTTP.

brew install skopeo   # one-time
make docker-build docker-push
make registry-tags

Safety model

Three layers, because an assistant driving a download client can do real damage:

  1. Registration filters--read-only / --disable-destructive / --toolsets decide what exists at all.
  2. Tool annotations — every tool is marked read-only, write, or destructive, so clients can apply their own policy.
  3. Confirmation gates — anything that starts a download, deletes data, or subscribes to a whole back catalogue requires confirm=true, and uses MCP elicitation to ask the user directly where the client supports it.

Credentials are masked on the way out: indexer and download-client API keys, and anything credential-shaped in the settings blob, are truncated to abcd...wxyz before the model ever sees them.

Development

make check      # gofmt check, go vet, go test
make build      # binary into build/
make test

Layout follows jellyfin-mcp:

main.go                        CLI entrypoint (cobra)
internal/listenarr/            API client, helpers, extractors, input/output types
internal/server/               transports, middleware, subscriptions, completions
internal/server/tools/         the 15 tools, grouped by toolset
internal/server/resources/     resources and reference guides
internal/server/prompts/       guided workflow prompts
k8s/                           ToolHive MCPServer + plain-Kubernetes manifests

Licence

MIT

Contributors

leachuk

1 commits

leachuk/listenarr-mcp

1

stars

1

commits

Go

primary language

Aug 19, 2026

updated

README

listenarr-mcp

A Model Context Protocol server for Listenarr, the automated audiobook collection manager. It lets an AI assistant browse your library, search the Audible catalogue, grab releases from your indexers, and diagnose downloads that got stuck — through Listenarr's own REST API.

Built in Go, following the architecture of jellyfin-mcp.

Note. There is a dependency on a local docker registry if you're deploying this to a local k8s node. You'll need to change this for your own k8s setup. See https://github.com/leachuk/listenarr-mcp/blob/main/k8s/plain/deployment.yaml

What it can do

15 tools across 7 toolsets:

ToolsetToolsWhat it covers
librarylistenarr_library, listenarr_library_add, listenarr_library_edit, listenarr_library_deleteBrowse and filter the collection, add books by ASIN, edit monitoring and metadata, rename/move files, delete entries
searchlistenarr_search, listenarr_metadataAudible catalogue lookups (with fuzzy ranking), indexer release searches, author and series catalogues
downloadslistenarr_downloads, listenarr_download_grab, listenarr_download_manageWatch transfers, grab releases, retry blocked imports, cancel and purge
monitoringlistenarr_monitoringStanding subscriptions to an author or a series
indexerslistenarr_indexersInspect, test, toggle, and remove indexers
configlistenarr_configRoot folders, quality profiles, download clients, settings (credentials masked)
systemlistenarr_system, listenarr_historyConnectivity, health, storage, logs, and the activity audit trail

Plus 13 resources (library, wanted list, active downloads, queue, health, root folders, indexers, recent history, per-book detail, and four reference guides) and 6 prompts for guided workflows: find-and-add, whats-downloading, finish-series, library-health, follow-author, and diagnose-stuck-download.

The one distinction that matters

Three things all look like "search", and they are not interchangeable:

listenarr_library      action=list          → what you ALREADY HAVE
listenarr_search       action=metadata      → the Audible CATALOGUE  → yields an ASIN
listenarr_search       action=indexers      → downloadable RELEASES  → yields a download_reference

The server's instructions spell this out to the model, because getting it wrong is the most common way an assistant wastes calls on this kind of API.

Configuration

VariableRequiredDefaultNotes
LISTENARR_API_KEYyesListenarr → Settings → General
LISTENARR_URLnohttp://listenarr:4545In-cluster Service DNS name when running in Kubernetes
LISTENARR_API_VERSIONnov1URL segment; only change if Listenarr ships a v2
LISTENARR_TIMEOUT_SECONDSno60Raise if indexer searches time out

The server authenticates to Listenarr with the X-Api-Key header.

Flags

--toolsets library,search,system   register only these tool groups
--read-only                        register only tools that cannot change anything
--disable-destructive              allow writes, but no deletes or cancellations
--http                             serve streamable HTTP instead of stdio
--addr 0.0.0.0:8080                HTTP listen address
--http-token <secret>              bearer token; REQUIRED for non-localhost binds

--read-only and --disable-destructive are enforced at registration time: a tool that is never registered cannot be called, whatever the model attempts.

Running it

Locally, over stdio

cp .env.example .env && $EDITOR .env
make run

Or point an MCP client at the binary:

{
  "mcpServers": {
    "listenarr": {
      "command": "/path/to/listenarr-mcp",
      "env": {
        "LISTENARR_URL": "http://192.168.0.129:30545",
        "LISTENARR_API_KEY": "your-api-key"
      }
    }
  }
}

On Kubernetes (this cluster)

MCP servers here run under ToolHive in the mcp namespace, alongside mcp-jellyfin and mcp-arr. ToolHive runs the container over stdio and fronts it with its own streamable-HTTP proxy.

# 1. Build and publish the image to the local registry
make docker-build docker-push

# 2. Create the API key secret
make k8s-secret

# 3. Create the MCPServer (and optional NodePort on 30802)
make k8s-apply

# 4. Check it came up
make k8s-status

The endpoint is then:

http://mcp-mcp-listenarr-proxy.mcp.svc.cluster.local:8080/mcp

Manifests live in k8s/. See k8s/README.md for the details, including a plain-Kubernetes alternative in k8s/plain/ for running without ToolHive.

Publishing to the local registry

make docker-push uses skopeo, not docker push. Two reasons, both specific to this setup:

  • the registry at 192.168.0.129:30050 serves plain HTTP, and Docker refuses that without an insecure-registries entry;
  • Docker Desktop's Linux VM cannot route to that LAN address at all, while the Mac itself can.

skopeo runs natively on the host and --dest-tls-verify=false handles the HTTP.

brew install skopeo   # one-time
make docker-build docker-push
make registry-tags

Safety model

Three layers, because an assistant driving a download client can do real damage:

  1. Registration filters--read-only / --disable-destructive / --toolsets decide what exists at all.
  2. Tool annotations — every tool is marked read-only, write, or destructive, so clients can apply their own policy.
  3. Confirmation gates — anything that starts a download, deletes data, or subscribes to a whole back catalogue requires confirm=true, and uses MCP elicitation to ask the user directly where the client supports it.

Credentials are masked on the way out: indexer and download-client API keys, and anything credential-shaped in the settings blob, are truncated to abcd...wxyz before the model ever sees them.

Development

make check      # gofmt check, go vet, go test
make build      # binary into build/
make test

Layout follows jellyfin-mcp:

main.go                        CLI entrypoint (cobra)
internal/listenarr/            API client, helpers, extractors, input/output types
internal/server/               transports, middleware, subscriptions, completions
internal/server/tools/         the 15 tools, grouped by toolset
internal/server/resources/     resources and reference guides
internal/server/prompts/       guided workflow prompts
k8s/                           ToolHive MCPServer + plain-Kubernetes manifests

Licence

MIT

See what people are saying

Contributors

leachuk

1 commits

Languages

Go

97.1%

Makefile

1.8%

Dockerfile

1.1%