Qbt Kit

Communauté Autres

qBittorrent WebUI API: all 123 endpoints, with confirmation required on destructive operations and a read-only mode that holds through the raw call.

Que pouvez-vous faire avec Qbt Kit ?

  • All 123 endpoints of qBittorrent 5.2.3, each one a spec entry that
  • A verifiable coverage claim. The endpoint list is extracted from the
  • An MCP server with 15 tools — 13 task-shaped, plus qbt_call and
  • Compatibility measured, not assumed — tested against real 4.6, 5.0, 5.1
  • Typed throughout, no runtime dependency beyond httpx and typer.

Installation

Les étapes d'installation sont dans la documentation ci-dessous. Documentation

Documentation

Tirée du README du projet sur GitHub, actualisée chaque semaine. Les liens ouvrent GitHub.

Sommaire
  1. qbt-kit
  2. Highlights
  3. Installation
  4. Quickstart
  5. MCP server
  6. Documentation
  7. Field notes
  8. Contributing
  9. Acknowledgements
  10. Licence

qbt-kit

A complete, typed Python client for the qBittorrent WebUI API — with a CLI that covers every endpoint one-to-one, and an MCP server so coding agents can drive it without deleting your data.

$ qbt coverage

qbt-kit coverage — target release-5.2.3

  scope               n   spec  progress
  torrents           61     61  ████████████████████  61/61
  app                16     16  ████████████████████  16/16
  rss                14     14  ████████████████████  14/14
  search             11     11  ████████████████████  11/11
  transfer            9      9  ████████████████████  9/9
  torrentcreator      4      4  ████████████████████  4/4
  auth                2      2  ████████████████████  2/2
  clientdata          2      2  ████████████████████  2/2
  log                 2      2  ████████████████████  2/2
  sync                2      2  ████████████████████  2/2
                   ----
  TOTAL             123    123  ████████████████████  100.0%

The ledger is generated from qBittorrent's own source, and CI fails if it slips.

Highlights

  • All 123 endpoints of qBittorrent 5.2.3, each one a spec entry that generates the client method, the CLI command and the docs together.
  • A verifiable coverage claim. The endpoint list is extracted from the qBittorrent C++ source per release tag and committed, so CI fails both when the spec misses an endpoint and when it invents one.
  • An MCP server with 15 tools — 13 task-shaped, plus qbt_call and list_endpoints — and safety gates that hold even through the escape hatch.
  • Compatibility measured, not assumed — tested against real 4.6, 5.0, 5.1 and 5.2 containers, with a rename table so torrents/stop resolves to pause on servers that predate the rename.
  • Typed throughout, no runtime dependency beyond httpx and typer.

That coverage claim is worth a sentence of context. The wiki page most clients are written against documents 78 endpoints. qBittorrent 5.2.3 ships 123, and two whole scopes — torrentcreator and clientdata — appear in no wiki page at all.

Installation

PyPI's qbt name belongs to an unrelated package, so the CLI is run via --from:

uvx --from qbt-kit qbt doctor
uvx --from "qbt-kit[mcp]" qbt-mcp --help   # the server lives in the `mcp` extra

Both run via --from because the qbt name on PyPI belongs to an unrelated package, and qbt-mcp is a script inside this one rather than a package of its own — uvx qbt-mcp resolves to nothing.

Or add it to a project:

uv add qbt-kit              # library and CLI
uv add "qbt-kit[mcp]"       # with the MCP server
As a Claude Code plugin

This repository is also a plugin marketplace, so one line installs the MCP server and the skill together:

/plugin install qbt-kit --marketplace manueltarouca/qbt-kit

The bundled MCP server runs from the plugin's own checkout, so it needs uv but not a published package, and it always matches the version you installed. Point it at your server with QBT_URL, and see Configuration for credentials.

Quickstart

qbt doctor                          # version, auth mode, endpoint availability
qbt torrents info --category tv     # the API calls this `info`, not `list`
qbt torrents add --urls <magnet> --category tv --auto-tmm
qbt health                          # swarm health across the queue
qbt coverage                        # the endpoint coverage ledger
qbt call torrents/pieceStates -p hash=<h>    # raw, reaches all 123

Scope commands mirror the API exactly — torrents info, not a friendlier list — so anything you read in qBittorrent's own docs translates directly. --json works everywhere, so every command composes with jq.

qbt ready is also there, but it inspects the local filesystem to decide whether a download has really settled, so it only means anything when the CLI runs on the same machine as qBittorrent.

MCP server

{
  "mcpServers": {
    "qbittorrent": {
      "command": "uvx",
      "args": ["--from", "qbt-kit[mcp]", "qbt-mcp", "--url", "http://127.0.0.1:8080"]
    }
  }
}

Fifteen tools rather than 123 — a tool list that long costs context on every turn and measurably worsens which tool a model picks. qbt_call keeps every endpoint reachable and list_endpoints lets a model discover them, so the small surface stays complete.

Configuration

Flags first, then the environment, then the macOS Keychain:

variablemeaning
QBT_URLbase URL, default http://127.0.0.1:8080
QBT_API_KEYAPI key (qBittorrent 5.2+); preferred when present
QBT_USERNAMEWebUI username, for cookie login on any version
QBT_PASSWORDWebUI password
QBT_READ_ONLY1/true/yes to refuse everything that changes state

Keychain fallback uses service qbittorrent, account api-key for a key and webui for the password:

security add-generic-password -s qbittorrent -a api-key -w '<key>'

qBittorrent has no OAuth, so there is no token flow to delegate and the secret is long-lived. The reference MCP servers put credentials straight into the client's env block — GITHUB_PERSONAL_ACCESS_TOKEN is the canonical example — but that file is plaintext and frequently committed. Prefer the Keychain, and if you do use env, reference a variable instead of pasting the secret:

"env": {
  "QBT_URL": "${QBT_URL:-http://127.0.0.1:8080}",
  "QBT_API_KEY": "${QBT_API_KEY:-}"      // empty falls through to the Keychain
}

The :- default matters. Claude Code passes an unset ${VAR} through as the literal text ${VAR} rather than as empty, which otherwise surfaces as a confusing 401 much later — so qbt-mcp detects that case at startup and says so plainly instead of starting.

On startup it reports, on stderr, where the credentials came from and never what they are:

qbt-mcp: http://127.0.0.1:8080 · WebAPI 2.15.1 · auth=bearer via macOS Keychain
Safety

An agent driving a torrent client can destroy data that took weeks to collect, so the gates are code rather than guidance:

  • Destructive endpoints require confirm; delete_files is never implied.
  • --read-only (or QBT_READ_ONLY=1) blocks mutations, including via qbt_call.
  • app/setPreferences refuses the WebUI, auth and network keys that would sever the connection or weaken security. There is no override.
  • Refusals return a structured cause and remedy, so an agent can correct itself instead of seeing an opaque tool error.

qbt-mcp speaks stdio by default, which keeps it a child process with nothing listening. The sse and streamable-http transports expose an unauthenticated control surface holding your qBittorrent credentials — bound to loopback, but do not forward those ports. See SECURITY.md.

Documentation

docs/TRACEABILITY.mdhow the coverage claim is built and gated
docs/TESTING.mdthe container harness, and behaviours that cost real time to learn
docs/PLAN.mdthe design and the reasoning behind it
docs/ROADMAP.mdwhat is done and what is not
docs/REVIEW-1.mdan independent review of the plan, with every finding dispositioned
docs/dependencies.mdevery dependency, and why it is justified
SECURITY.mdthreat model, credential handling, how to report a vulnerability

A Claude skill ships in skills/qbt-kit/ covering CLI usage and the swarm-health rule.

Field notes

Things that cost us time, documented so they cost you none.

  • Login success cannot be read from the status code. qBittorrent ≤5.1 answers a failed login with HTTP 200 and the body Fails.; 5.2 returns an empty 204. The only rule that holds across versions is whether a session cookie was issued.
  • app/webapiVersion requires authentication. Only auth/login is public, so you cannot read the version to decide how to authenticate. Probe instead.
  • The session cookie is not always SID. On 5.2 it is QBT_SID_<port>; on 5.0/5.1 it is user-configurable. Never match on the name.
  • A bare 401 is often Host-header validation, not bad credentials. It is on by default and rejects any request whose Host port differs from the port qBittorrent listens on — which is what happens behind mapped container ports, SSH tunnels and most reverse proxies.
  • API keys exist only from qBittorrent 5.2.0. Sending Authorization: Bearer to 5.0/5.1 gets a 403 that looks like a credentials problem.
  • pause/resume were removed in 5.0, not aliased; they 404 there.
  • progress: 1.0 does not mean every file is on disk. Progress is computed over the selected files, so a torrent with files at priority 0 reports 100% having never fetched them. size < total_size is the cheap flag, from the same listing call.
  • A category alone does not place a torrent. qBittorrent only applies a category's save path under automatic torrent management, so torrents/add with a category but without autoTMM files it in the global save path.
  • A stalled torrent is usually not slow but stuck. availability is how many complete copies exist across reachable peers; when it does not exceed progress, no peer has the missing pieces. But a queued torrent reports availability 0 simply for not being connected — judging those as dead is how you delete healthy downloads.

Contributing

See CONTRIBUTING.md. The short version: endpoints are added to the spec under src/qbtkit/spec/, never by hand to the CLI or MCP, and tools/build_coverage.py --strict has to stay green.

Acknowledgements

  • qBittorrent — and specifically its src/webui/api/*controller.cpp, which is the only complete and accurate description of this API that exists.
  • qbittorrent-api is the mature, well-maintained Python library for this API, and if a library is all you need, use it. qbt-kit exists for the CLI, the MCP server and the verifiable coverage claim, not because anything is wrong with it.

Licence

MIT — see LICENSE.

Questions fréquentes

Qu'est-ce que Qbt Kit ?

qBittorrent WebUI API: all 123 endpoints, with confirmation required on destructive operations and a read-only mode that holds through the raw call.

Comment installer Qbt Kit ?

Suivez les étapes d'installation de sa documentation, affichée sur cette page et dans son dépôt.

Qbt Kit est-il open source ?

Oui. Son code est sur GitHub sous licence MIT.

Qui maintient Qbt Kit ?

Il est publié par manueltarouca. AI.tn le référence sans le maintenir ni le recommander.

Issu des listes communautaires awesome-mcp-servers et du dépôt GitHub du projet. Être listé n'est pas une recommandation : vérifiez le code et les permissions d'un serveur avant de lui donner accès à vos données.